@midscene/shared 1.7.5-beta-20260420031652.0 → 1.7.5-beta-20260420031920.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.
- package/dist/es/cli/cli-runner.mjs +41 -4
- package/dist/es/key-alias-utils.mjs +19 -0
- package/dist/es/mcp/base-tools.mjs +43 -2
- package/dist/es/mcp/index.mjs +1 -0
- package/dist/es/mcp/init-arg-utils.mjs +38 -0
- package/dist/es/mcp/tool-generator.mjs +29 -11
- package/dist/lib/cli/cli-runner.js +41 -4
- package/dist/lib/key-alias-utils.js +62 -0
- package/dist/lib/mcp/base-tools.js +43 -2
- package/dist/lib/mcp/index.js +19 -12
- package/dist/lib/mcp/init-arg-utils.js +78 -0
- package/dist/lib/mcp/tool-generator.js +29 -11
- package/dist/types/cli/cli-runner.d.ts +3 -1
- package/dist/types/key-alias-utils.d.ts +9 -0
- package/dist/types/mcp/base-tools.d.ts +62 -5
- package/dist/types/mcp/index.d.ts +1 -0
- package/dist/types/mcp/init-arg-utils.d.ts +13 -0
- package/dist/types/mcp/tool-generator.d.ts +3 -3
- package/dist/types/mcp/types.d.ts +8 -0
- package/package.json +1 -1
- package/src/cli/cli-runner.ts +74 -5
- package/src/key-alias-utils.ts +23 -0
- package/src/mcp/base-tools.ts +162 -9
- package/src/mcp/index.ts +1 -0
- package/src/mcp/init-arg-utils.ts +105 -0
- package/src/mcp/tool-generator.ts +47 -10
- package/src/mcp/types.ts +10 -0
|
@@ -2,6 +2,7 @@ import { existsSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import dotenv from "dotenv";
|
|
5
|
+
import { getKeyAliases, isRecord } from "../key-alias-utils.mjs";
|
|
5
6
|
import { getDebug } from "../logger.mjs";
|
|
6
7
|
function _define_property(obj, key, value) {
|
|
7
8
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -28,16 +29,36 @@ function parseValue(raw) {
|
|
|
28
29
|
}
|
|
29
30
|
function parseCliArgs(args) {
|
|
30
31
|
const result = {};
|
|
32
|
+
const setArgValue = (key, value)=>{
|
|
33
|
+
if (!key.includes('.')) {
|
|
34
|
+
result[key] = value;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const segments = key.split('.');
|
|
38
|
+
let current = result;
|
|
39
|
+
for (const segment of segments.slice(0, -1)){
|
|
40
|
+
const aliases = getKeyAliases(segment);
|
|
41
|
+
const existing = aliases.map((alias)=>current[alias]);
|
|
42
|
+
const nestedRecord = existing.find(isRecord);
|
|
43
|
+
const conflictingScalar = existing.find((entry)=>void 0 !== entry && !isRecord(entry));
|
|
44
|
+
if (void 0 !== conflictingScalar) throw new CLIError(`Conflicting CLI args: "${segment}" is used both as a value and as a namespace`);
|
|
45
|
+
const target = nestedRecord ?? {};
|
|
46
|
+
for (const alias of aliases)current[alias] = target;
|
|
47
|
+
current = target;
|
|
48
|
+
}
|
|
49
|
+
const leafSegment = segments[segments.length - 1];
|
|
50
|
+
for (const alias of getKeyAliases(leafSegment))current[alias] = value;
|
|
51
|
+
};
|
|
31
52
|
for(let i = 0; i < args.length; i++){
|
|
32
53
|
const arg = args[i];
|
|
33
54
|
if (!arg.startsWith('--')) continue;
|
|
34
55
|
const body = arg.slice(2);
|
|
35
56
|
const eqIdx = body.indexOf('=');
|
|
36
|
-
if (eqIdx >= 0)
|
|
57
|
+
if (eqIdx >= 0) setArgValue(body.slice(0, eqIdx), parseValue(body.slice(eqIdx + 1)));
|
|
37
58
|
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
38
59
|
i++;
|
|
39
|
-
|
|
40
|
-
} else
|
|
60
|
+
setArgValue(body, parseValue(args[i]));
|
|
61
|
+
} else setArgValue(body, true);
|
|
41
62
|
}
|
|
42
63
|
return result;
|
|
43
64
|
}
|
|
@@ -66,16 +87,32 @@ function removePrefix(name, prefix) {
|
|
|
66
87
|
if (prefix && name.startsWith(prefix)) return name.slice(prefix.length);
|
|
67
88
|
return name;
|
|
68
89
|
}
|
|
90
|
+
function formatCliOptionName(name) {
|
|
91
|
+
return `--${name}`;
|
|
92
|
+
}
|
|
93
|
+
function getCliOptionDisplay(key, cliOption) {
|
|
94
|
+
const label = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
95
|
+
const aliases = [
|
|
96
|
+
...new Set(cliOption?.aliases ?? [])
|
|
97
|
+
].map((alias)=>formatCliOptionName(alias)).filter((alias)=>alias !== label);
|
|
98
|
+
return {
|
|
99
|
+
label,
|
|
100
|
+
aliases
|
|
101
|
+
};
|
|
102
|
+
}
|
|
69
103
|
function printCommandHelp(scriptName, cmd) {
|
|
70
104
|
const { def } = cmd;
|
|
71
105
|
console.log(`\nUsage: ${scriptName} ${cmd.name} [options]\n`);
|
|
72
106
|
console.log(def.description);
|
|
73
107
|
const schemaEntries = Object.entries(def.schema);
|
|
74
108
|
if (schemaEntries.length > 0) {
|
|
109
|
+
const optionWidth = Math.max(22, ...schemaEntries.map(([key])=>getCliOptionDisplay(key, def.cli?.options?.[key]).label.length));
|
|
75
110
|
console.log('\nOptions:');
|
|
76
111
|
for (const [key, zodType] of schemaEntries){
|
|
112
|
+
const { label, aliases } = getCliOptionDisplay(key, def.cli?.options?.[key]);
|
|
77
113
|
const desc = zodType.description ?? '';
|
|
78
|
-
|
|
114
|
+
const aliasText = aliases.length > 0 ? ` (aliases: ${aliases.join(', ')})` : '';
|
|
115
|
+
console.log(` ${label.padEnd(optionWidth)} ${desc}${aliasText}`);
|
|
79
116
|
}
|
|
80
117
|
}
|
|
81
118
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function kebabToCamel(str) {
|
|
2
|
+
return str.replace(/-([a-z])/g, (_, letter)=>letter.toUpperCase());
|
|
3
|
+
}
|
|
4
|
+
function camelToKebab(str) {
|
|
5
|
+
return str.replace(/[A-Z]/g, (letter)=>`-${letter.toLowerCase()}`).replace(/^-/, '');
|
|
6
|
+
}
|
|
7
|
+
function getKeyAliases(key) {
|
|
8
|
+
return [
|
|
9
|
+
...new Set([
|
|
10
|
+
key,
|
|
11
|
+
kebabToCamel(key),
|
|
12
|
+
camelToKebab(key)
|
|
13
|
+
])
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
function isRecord(value) {
|
|
17
|
+
return 'object' == typeof value && null !== value && !Array.isArray(value);
|
|
18
|
+
}
|
|
19
|
+
export { camelToKebab, getKeyAliases, isRecord, kebabToCamel };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { parseBase64 } from "@midscene/shared/img";
|
|
2
2
|
import { getDebug } from "@midscene/shared/logger";
|
|
3
|
+
import { camelToKebab, getKeyAliases } from "../key-alias-utils.mjs";
|
|
4
|
+
import { createNamespacedInitArgSchema, extractNamespacedArgs, sanitizeNamespacedArgs } from "./init-arg-utils.mjs";
|
|
3
5
|
import { generateCommonTools, generateToolsFromActionSpace } from "./tool-generator.mjs";
|
|
4
6
|
function _define_property(obj, key, value) {
|
|
5
7
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -13,6 +15,45 @@ function _define_property(obj, key, value) {
|
|
|
13
15
|
}
|
|
14
16
|
const debug = getDebug('mcp:base-tools');
|
|
15
17
|
class BaseMidsceneTools {
|
|
18
|
+
getInitArgKeys() {
|
|
19
|
+
return this.initArgSpec ? Object.keys(this.initArgSpec.shape) : [];
|
|
20
|
+
}
|
|
21
|
+
extractAgentInitParam(args) {
|
|
22
|
+
if (!this.initArgSpec) return;
|
|
23
|
+
const extracted = extractNamespacedArgs(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
24
|
+
if (this.initArgSpec.adapt) return this.initArgSpec.adapt(extracted);
|
|
25
|
+
return extracted;
|
|
26
|
+
}
|
|
27
|
+
sanitizeToolArgs(args) {
|
|
28
|
+
if (!this.initArgSpec) return args;
|
|
29
|
+
return sanitizeNamespacedArgs(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
30
|
+
}
|
|
31
|
+
getAgentInitArgSchema() {
|
|
32
|
+
if (!this.initArgSpec) return {};
|
|
33
|
+
return createNamespacedInitArgSchema(this.initArgSpec.namespace, this.initArgSpec.shape);
|
|
34
|
+
}
|
|
35
|
+
getAgentInitArgCliMetadata() {
|
|
36
|
+
if (!this.initArgSpec?.cli) return;
|
|
37
|
+
const options = Object.fromEntries(this.getInitArgKeys().map((key)=>{
|
|
38
|
+
const canonicalKey = `${this.initArgSpec.namespace}.${key}`;
|
|
39
|
+
const preferredName = this.initArgSpec.cli?.preferredNames?.[key] ?? (this.initArgSpec.cli?.preferBareKeys ? camelToKebab(key) : canonicalKey);
|
|
40
|
+
const aliases = new Set(getKeyAliases(canonicalKey));
|
|
41
|
+
if (this.initArgSpec.cli?.preferBareKeys) for (const alias of getKeyAliases(key))aliases.add(alias);
|
|
42
|
+
aliases.delete(preferredName);
|
|
43
|
+
return [
|
|
44
|
+
canonicalKey,
|
|
45
|
+
{
|
|
46
|
+
preferredName,
|
|
47
|
+
aliases: [
|
|
48
|
+
...aliases
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
}));
|
|
53
|
+
return {
|
|
54
|
+
options
|
|
55
|
+
};
|
|
56
|
+
}
|
|
16
57
|
preparePlatformTools() {
|
|
17
58
|
return [];
|
|
18
59
|
}
|
|
@@ -30,8 +71,8 @@ class BaseMidsceneTools {
|
|
|
30
71
|
await tempDevice.destroy?.();
|
|
31
72
|
debug('Action space from temporary device:', actionSpace.map((a)=>a.name).join(', '));
|
|
32
73
|
}
|
|
33
|
-
const actionTools = generateToolsFromActionSpace(actionSpace, ()=>this.ensureAgent());
|
|
34
|
-
const commonTools = generateCommonTools(()=>this.ensureAgent());
|
|
74
|
+
const actionTools = generateToolsFromActionSpace(actionSpace, (args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), (args = {})=>this.sanitizeToolArgs(args), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata());
|
|
75
|
+
const commonTools = generateCommonTools((args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata());
|
|
35
76
|
this.toolDefinitions.push(...actionTools, ...commonTools);
|
|
36
77
|
debug('Total tools prepared:', this.toolDefinitions.length);
|
|
37
78
|
}
|
package/dist/es/mcp/index.mjs
CHANGED
|
@@ -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 };
|
|
@@ -277,17 +277,30 @@ async function captureFailureResult(agent, actionName, errorMessage) {
|
|
|
277
277
|
};
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
|
-
function
|
|
280
|
+
function mergeToolCliMetadata(base, extra) {
|
|
281
|
+
const options = {
|
|
282
|
+
...base?.options ?? {},
|
|
283
|
+
...extra?.options ?? {}
|
|
284
|
+
};
|
|
285
|
+
return Object.keys(options).length > 0 ? {
|
|
286
|
+
options
|
|
287
|
+
} : void 0;
|
|
288
|
+
}
|
|
289
|
+
function generateToolsFromActionSpace(actionSpace, getAgent, sanitizeArgs = (args)=>args, initArgSchema = {}, initArgCliMetadata) {
|
|
281
290
|
return actionSpace.map((action)=>{
|
|
282
|
-
const schema =
|
|
291
|
+
const schema = {
|
|
292
|
+
...extractActionSchema(action.paramSchema),
|
|
293
|
+
...initArgSchema
|
|
294
|
+
};
|
|
283
295
|
return {
|
|
284
296
|
name: action.name,
|
|
285
297
|
description: describeActionForMCP(action),
|
|
286
298
|
schema,
|
|
299
|
+
cli: initArgCliMetadata,
|
|
287
300
|
handler: async (args)=>{
|
|
288
301
|
try {
|
|
289
|
-
const agent = await getAgent();
|
|
290
|
-
const normalizedArgs = normalizeActionArgs(args, action.paramSchema);
|
|
302
|
+
const agent = await getAgent(args);
|
|
303
|
+
const normalizedArgs = normalizeActionArgs(sanitizeArgs(args), action.paramSchema);
|
|
291
304
|
let actionResult;
|
|
292
305
|
try {
|
|
293
306
|
actionResult = await executeAction(agent, action.name, normalizedArgs);
|
|
@@ -306,15 +319,18 @@ function generateToolsFromActionSpace(actionSpace, getAgent) {
|
|
|
306
319
|
};
|
|
307
320
|
});
|
|
308
321
|
}
|
|
309
|
-
function generateCommonTools(getAgent) {
|
|
322
|
+
function generateCommonTools(getAgent, initArgSchema = {}, initArgCliMetadata) {
|
|
310
323
|
return [
|
|
311
324
|
{
|
|
312
325
|
name: 'take_screenshot',
|
|
313
326
|
description: 'Capture screenshot of current page/screen',
|
|
314
|
-
schema: {
|
|
315
|
-
|
|
327
|
+
schema: {
|
|
328
|
+
...initArgSchema
|
|
329
|
+
},
|
|
330
|
+
cli: initArgCliMetadata,
|
|
331
|
+
handler: async (args = {})=>{
|
|
316
332
|
try {
|
|
317
|
-
const agent = await getAgent();
|
|
333
|
+
const agent = await getAgent(args);
|
|
318
334
|
const screenshot = await agent.page?.screenshotBase64();
|
|
319
335
|
if (!screenshot) return createErrorResult('Screenshot not available');
|
|
320
336
|
const { mimeType, body } = parseBase64(screenshot);
|
|
@@ -338,12 +354,14 @@ function generateCommonTools(getAgent) {
|
|
|
338
354
|
name: 'act',
|
|
339
355
|
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.',
|
|
340
356
|
schema: {
|
|
341
|
-
prompt: z.string().describe('Natural language description of the action to perform, e.g. "press Command+Space, type Safari, press Enter"')
|
|
357
|
+
prompt: z.string().describe('Natural language description of the action to perform, e.g. "press Command+Space, type Safari, press Enter"'),
|
|
358
|
+
...initArgSchema
|
|
342
359
|
},
|
|
343
|
-
|
|
360
|
+
cli: mergeToolCliMetadata(void 0, initArgCliMetadata),
|
|
361
|
+
handler: async (args = {})=>{
|
|
344
362
|
const prompt = args.prompt;
|
|
345
363
|
try {
|
|
346
|
-
const agent = await getAgent();
|
|
364
|
+
const agent = await getAgent(args);
|
|
347
365
|
if (!agent.aiAction) return createErrorResult('act is not supported by this agent');
|
|
348
366
|
const result = await agent.aiAction(prompt, {
|
|
349
367
|
deepThink: false
|
|
@@ -44,6 +44,7 @@ const external_node_os_namespaceObject = require("node:os");
|
|
|
44
44
|
const external_node_path_namespaceObject = require("node:path");
|
|
45
45
|
const external_dotenv_namespaceObject = require("dotenv");
|
|
46
46
|
var external_dotenv_default = /*#__PURE__*/ __webpack_require__.n(external_dotenv_namespaceObject);
|
|
47
|
+
const external_key_alias_utils_js_namespaceObject = require("../key-alias-utils.js");
|
|
47
48
|
const external_logger_js_namespaceObject = require("../logger.js");
|
|
48
49
|
function _define_property(obj, key, value) {
|
|
49
50
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -70,16 +71,36 @@ function parseValue(raw) {
|
|
|
70
71
|
}
|
|
71
72
|
function parseCliArgs(args) {
|
|
72
73
|
const result = {};
|
|
74
|
+
const setArgValue = (key, value)=>{
|
|
75
|
+
if (!key.includes('.')) {
|
|
76
|
+
result[key] = value;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const segments = key.split('.');
|
|
80
|
+
let current = result;
|
|
81
|
+
for (const segment of segments.slice(0, -1)){
|
|
82
|
+
const aliases = (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(segment);
|
|
83
|
+
const existing = aliases.map((alias)=>current[alias]);
|
|
84
|
+
const nestedRecord = existing.find(external_key_alias_utils_js_namespaceObject.isRecord);
|
|
85
|
+
const conflictingScalar = existing.find((entry)=>void 0 !== entry && !(0, external_key_alias_utils_js_namespaceObject.isRecord)(entry));
|
|
86
|
+
if (void 0 !== conflictingScalar) throw new CLIError(`Conflicting CLI args: "${segment}" is used both as a value and as a namespace`);
|
|
87
|
+
const target = nestedRecord ?? {};
|
|
88
|
+
for (const alias of aliases)current[alias] = target;
|
|
89
|
+
current = target;
|
|
90
|
+
}
|
|
91
|
+
const leafSegment = segments[segments.length - 1];
|
|
92
|
+
for (const alias of (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(leafSegment))current[alias] = value;
|
|
93
|
+
};
|
|
73
94
|
for(let i = 0; i < args.length; i++){
|
|
74
95
|
const arg = args[i];
|
|
75
96
|
if (!arg.startsWith('--')) continue;
|
|
76
97
|
const body = arg.slice(2);
|
|
77
98
|
const eqIdx = body.indexOf('=');
|
|
78
|
-
if (eqIdx >= 0)
|
|
99
|
+
if (eqIdx >= 0) setArgValue(body.slice(0, eqIdx), parseValue(body.slice(eqIdx + 1)));
|
|
79
100
|
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
80
101
|
i++;
|
|
81
|
-
|
|
82
|
-
} else
|
|
102
|
+
setArgValue(body, parseValue(args[i]));
|
|
103
|
+
} else setArgValue(body, true);
|
|
83
104
|
}
|
|
84
105
|
return result;
|
|
85
106
|
}
|
|
@@ -108,16 +129,32 @@ function removePrefix(name, prefix) {
|
|
|
108
129
|
if (prefix && name.startsWith(prefix)) return name.slice(prefix.length);
|
|
109
130
|
return name;
|
|
110
131
|
}
|
|
132
|
+
function formatCliOptionName(name) {
|
|
133
|
+
return `--${name}`;
|
|
134
|
+
}
|
|
135
|
+
function getCliOptionDisplay(key, cliOption) {
|
|
136
|
+
const label = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
137
|
+
const aliases = [
|
|
138
|
+
...new Set(cliOption?.aliases ?? [])
|
|
139
|
+
].map((alias)=>formatCliOptionName(alias)).filter((alias)=>alias !== label);
|
|
140
|
+
return {
|
|
141
|
+
label,
|
|
142
|
+
aliases
|
|
143
|
+
};
|
|
144
|
+
}
|
|
111
145
|
function printCommandHelp(scriptName, cmd) {
|
|
112
146
|
const { def } = cmd;
|
|
113
147
|
console.log(`\nUsage: ${scriptName} ${cmd.name} [options]\n`);
|
|
114
148
|
console.log(def.description);
|
|
115
149
|
const schemaEntries = Object.entries(def.schema);
|
|
116
150
|
if (schemaEntries.length > 0) {
|
|
151
|
+
const optionWidth = Math.max(22, ...schemaEntries.map(([key])=>getCliOptionDisplay(key, def.cli?.options?.[key]).label.length));
|
|
117
152
|
console.log('\nOptions:');
|
|
118
153
|
for (const [key, zodType] of schemaEntries){
|
|
154
|
+
const { label, aliases } = getCliOptionDisplay(key, def.cli?.options?.[key]);
|
|
119
155
|
const desc = zodType.description ?? '';
|
|
120
|
-
|
|
156
|
+
const aliasText = aliases.length > 0 ? ` (aliases: ${aliases.join(', ')})` : '';
|
|
157
|
+
console.log(` ${label.padEnd(optionWidth)} ${desc}${aliasText}`);
|
|
121
158
|
}
|
|
122
159
|
}
|
|
123
160
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
camelToKebab: ()=>camelToKebab,
|
|
28
|
+
getKeyAliases: ()=>getKeyAliases,
|
|
29
|
+
isRecord: ()=>isRecord,
|
|
30
|
+
kebabToCamel: ()=>kebabToCamel
|
|
31
|
+
});
|
|
32
|
+
function kebabToCamel(str) {
|
|
33
|
+
return str.replace(/-([a-z])/g, (_, letter)=>letter.toUpperCase());
|
|
34
|
+
}
|
|
35
|
+
function camelToKebab(str) {
|
|
36
|
+
return str.replace(/[A-Z]/g, (letter)=>`-${letter.toLowerCase()}`).replace(/^-/, '');
|
|
37
|
+
}
|
|
38
|
+
function getKeyAliases(key) {
|
|
39
|
+
return [
|
|
40
|
+
...new Set([
|
|
41
|
+
key,
|
|
42
|
+
kebabToCamel(key),
|
|
43
|
+
camelToKebab(key)
|
|
44
|
+
])
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
function isRecord(value) {
|
|
48
|
+
return 'object' == typeof value && null !== value && !Array.isArray(value);
|
|
49
|
+
}
|
|
50
|
+
exports.camelToKebab = __webpack_exports__.camelToKebab;
|
|
51
|
+
exports.getKeyAliases = __webpack_exports__.getKeyAliases;
|
|
52
|
+
exports.isRecord = __webpack_exports__.isRecord;
|
|
53
|
+
exports.kebabToCamel = __webpack_exports__.kebabToCamel;
|
|
54
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
55
|
+
"camelToKebab",
|
|
56
|
+
"getKeyAliases",
|
|
57
|
+
"isRecord",
|
|
58
|
+
"kebabToCamel"
|
|
59
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
60
|
+
Object.defineProperty(exports, '__esModule', {
|
|
61
|
+
value: true
|
|
62
|
+
});
|
|
@@ -28,6 +28,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
28
28
|
});
|
|
29
29
|
const img_namespaceObject = require("@midscene/shared/img");
|
|
30
30
|
const logger_namespaceObject = require("@midscene/shared/logger");
|
|
31
|
+
const external_key_alias_utils_js_namespaceObject = require("../key-alias-utils.js");
|
|
32
|
+
const external_init_arg_utils_js_namespaceObject = require("./init-arg-utils.js");
|
|
31
33
|
const external_tool_generator_js_namespaceObject = require("./tool-generator.js");
|
|
32
34
|
function _define_property(obj, key, value) {
|
|
33
35
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -41,6 +43,45 @@ function _define_property(obj, key, value) {
|
|
|
41
43
|
}
|
|
42
44
|
const debug = (0, logger_namespaceObject.getDebug)('mcp:base-tools');
|
|
43
45
|
class BaseMidsceneTools {
|
|
46
|
+
getInitArgKeys() {
|
|
47
|
+
return this.initArgSpec ? Object.keys(this.initArgSpec.shape) : [];
|
|
48
|
+
}
|
|
49
|
+
extractAgentInitParam(args) {
|
|
50
|
+
if (!this.initArgSpec) return;
|
|
51
|
+
const extracted = (0, external_init_arg_utils_js_namespaceObject.extractNamespacedArgs)(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
52
|
+
if (this.initArgSpec.adapt) return this.initArgSpec.adapt(extracted);
|
|
53
|
+
return extracted;
|
|
54
|
+
}
|
|
55
|
+
sanitizeToolArgs(args) {
|
|
56
|
+
if (!this.initArgSpec) return args;
|
|
57
|
+
return (0, external_init_arg_utils_js_namespaceObject.sanitizeNamespacedArgs)(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
58
|
+
}
|
|
59
|
+
getAgentInitArgSchema() {
|
|
60
|
+
if (!this.initArgSpec) return {};
|
|
61
|
+
return (0, external_init_arg_utils_js_namespaceObject.createNamespacedInitArgSchema)(this.initArgSpec.namespace, this.initArgSpec.shape);
|
|
62
|
+
}
|
|
63
|
+
getAgentInitArgCliMetadata() {
|
|
64
|
+
if (!this.initArgSpec?.cli) return;
|
|
65
|
+
const options = Object.fromEntries(this.getInitArgKeys().map((key)=>{
|
|
66
|
+
const canonicalKey = `${this.initArgSpec.namespace}.${key}`;
|
|
67
|
+
const preferredName = this.initArgSpec.cli?.preferredNames?.[key] ?? (this.initArgSpec.cli?.preferBareKeys ? (0, external_key_alias_utils_js_namespaceObject.camelToKebab)(key) : canonicalKey);
|
|
68
|
+
const aliases = new Set((0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(canonicalKey));
|
|
69
|
+
if (this.initArgSpec.cli?.preferBareKeys) for (const alias of (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(key))aliases.add(alias);
|
|
70
|
+
aliases.delete(preferredName);
|
|
71
|
+
return [
|
|
72
|
+
canonicalKey,
|
|
73
|
+
{
|
|
74
|
+
preferredName,
|
|
75
|
+
aliases: [
|
|
76
|
+
...aliases
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
}));
|
|
81
|
+
return {
|
|
82
|
+
options
|
|
83
|
+
};
|
|
84
|
+
}
|
|
44
85
|
preparePlatformTools() {
|
|
45
86
|
return [];
|
|
46
87
|
}
|
|
@@ -58,8 +99,8 @@ class BaseMidsceneTools {
|
|
|
58
99
|
await tempDevice.destroy?.();
|
|
59
100
|
debug('Action space from temporary device:', actionSpace.map((a)=>a.name).join(', '));
|
|
60
101
|
}
|
|
61
|
-
const actionTools = (0, external_tool_generator_js_namespaceObject.generateToolsFromActionSpace)(actionSpace, ()=>this.ensureAgent());
|
|
62
|
-
const commonTools = (0, external_tool_generator_js_namespaceObject.generateCommonTools)(()=>this.ensureAgent());
|
|
102
|
+
const actionTools = (0, external_tool_generator_js_namespaceObject.generateToolsFromActionSpace)(actionSpace, (args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), (args = {})=>this.sanitizeToolArgs(args), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata());
|
|
103
|
+
const commonTools = (0, external_tool_generator_js_namespaceObject.generateCommonTools)((args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata());
|
|
63
104
|
this.toolDefinitions.push(...actionTools, ...commonTools);
|
|
64
105
|
debug('Total tools prepared:', this.toolDefinitions.length);
|
|
65
106
|
}
|
package/dist/lib/mcp/index.js
CHANGED
|
@@ -12,6 +12,9 @@ var __webpack_modules__ = {
|
|
|
12
12
|
"./error-formatter" (module) {
|
|
13
13
|
module.exports = require("./error-formatter.js");
|
|
14
14
|
},
|
|
15
|
+
"./init-arg-utils" (module) {
|
|
16
|
+
module.exports = require("./init-arg-utils.js");
|
|
17
|
+
},
|
|
15
18
|
"./inject-report-html-plugin" (module) {
|
|
16
19
|
module.exports = require("./inject-report-html-plugin.js");
|
|
17
20
|
},
|
|
@@ -76,29 +79,33 @@ var __webpack_exports__ = {};
|
|
|
76
79
|
var __rspack_reexport = {};
|
|
77
80
|
for(const __rspack_import_key in _base_tools__rspack_import_1)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_base_tools__rspack_import_1[__rspack_import_key];
|
|
78
81
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
79
|
-
var
|
|
82
|
+
var _init_arg_utils__rspack_import_2 = __webpack_require__("./init-arg-utils");
|
|
83
|
+
var __rspack_reexport = {};
|
|
84
|
+
for(const __rspack_import_key in _init_arg_utils__rspack_import_2)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_init_arg_utils__rspack_import_2[__rspack_import_key];
|
|
85
|
+
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
86
|
+
var _error_formatter__rspack_import_3 = __webpack_require__("./error-formatter");
|
|
80
87
|
var __rspack_reexport = {};
|
|
81
|
-
for(const __rspack_import_key in
|
|
88
|
+
for(const __rspack_import_key in _error_formatter__rspack_import_3)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_error_formatter__rspack_import_3[__rspack_import_key];
|
|
82
89
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
83
|
-
var
|
|
90
|
+
var _tool_generator__rspack_import_4 = __webpack_require__("./tool-generator");
|
|
84
91
|
var __rspack_reexport = {};
|
|
85
|
-
for(const __rspack_import_key in
|
|
92
|
+
for(const __rspack_import_key in _tool_generator__rspack_import_4)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_generator__rspack_import_4[__rspack_import_key];
|
|
86
93
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
87
|
-
var
|
|
94
|
+
var _types__rspack_import_5 = __webpack_require__("./types");
|
|
88
95
|
var __rspack_reexport = {};
|
|
89
|
-
for(const __rspack_import_key in
|
|
96
|
+
for(const __rspack_import_key in _types__rspack_import_5)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_types__rspack_import_5[__rspack_import_key];
|
|
90
97
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
91
|
-
var
|
|
98
|
+
var _inject_report_html_plugin__rspack_import_6 = __webpack_require__("./inject-report-html-plugin");
|
|
92
99
|
var __rspack_reexport = {};
|
|
93
|
-
for(const __rspack_import_key in
|
|
100
|
+
for(const __rspack_import_key in _inject_report_html_plugin__rspack_import_6)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_inject_report_html_plugin__rspack_import_6[__rspack_import_key];
|
|
94
101
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
95
|
-
var
|
|
102
|
+
var _launcher_helper__rspack_import_7 = __webpack_require__("./launcher-helper");
|
|
96
103
|
var __rspack_reexport = {};
|
|
97
|
-
for(const __rspack_import_key in
|
|
104
|
+
for(const __rspack_import_key in _launcher_helper__rspack_import_7)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_launcher_helper__rspack_import_7[__rspack_import_key];
|
|
98
105
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
99
|
-
var
|
|
106
|
+
var _chrome_path__rspack_import_8 = __webpack_require__("./chrome-path");
|
|
100
107
|
var __rspack_reexport = {};
|
|
101
|
-
for(const __rspack_import_key in
|
|
108
|
+
for(const __rspack_import_key in _chrome_path__rspack_import_8)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_chrome_path__rspack_import_8[__rspack_import_key];
|
|
102
109
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
103
110
|
})();
|
|
104
111
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
createNamespacedInitArgSchema: ()=>createNamespacedInitArgSchema,
|
|
28
|
+
extractNamespacedArgs: ()=>extractNamespacedArgs,
|
|
29
|
+
sanitizeNamespacedArgs: ()=>sanitizeNamespacedArgs
|
|
30
|
+
});
|
|
31
|
+
const external_key_alias_utils_js_namespaceObject = require("../key-alias-utils.js");
|
|
32
|
+
function readAliasedValue(args, key) {
|
|
33
|
+
for (const alias of (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(key))if (alias in args) return args[alias];
|
|
34
|
+
}
|
|
35
|
+
function readNamespacedArg(args, namespace, key) {
|
|
36
|
+
const namespacedArgs = readAliasedValue(args, namespace);
|
|
37
|
+
if ((0, external_key_alias_utils_js_namespaceObject.isRecord)(namespacedArgs)) {
|
|
38
|
+
const nestedValue = readAliasedValue(namespacedArgs, key);
|
|
39
|
+
if (void 0 !== nestedValue) return nestedValue;
|
|
40
|
+
}
|
|
41
|
+
const dottedValue = readAliasedValue(args, `${namespace}.${key}`);
|
|
42
|
+
if (void 0 !== dottedValue) return dottedValue;
|
|
43
|
+
const directValue = readAliasedValue(args, key);
|
|
44
|
+
if (void 0 !== directValue) return directValue;
|
|
45
|
+
}
|
|
46
|
+
function extractNamespacedArgs(args, namespace, keys) {
|
|
47
|
+
const extracted = {};
|
|
48
|
+
for (const key of keys){
|
|
49
|
+
const value = readNamespacedArg(args, namespace, key);
|
|
50
|
+
if (void 0 !== value) extracted[key] = value;
|
|
51
|
+
}
|
|
52
|
+
return Object.keys(extracted).length > 0 ? extracted : void 0;
|
|
53
|
+
}
|
|
54
|
+
function sanitizeNamespacedArgs(args, namespace, keys) {
|
|
55
|
+
const excludedKeys = new Set((0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(namespace));
|
|
56
|
+
for (const key of keys){
|
|
57
|
+
for (const alias of (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(key))excludedKeys.add(alias);
|
|
58
|
+
for (const alias of (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(`${namespace}.${key}`))excludedKeys.add(alias);
|
|
59
|
+
}
|
|
60
|
+
return Object.fromEntries(Object.entries(args).filter(([key])=>!excludedKeys.has(key)));
|
|
61
|
+
}
|
|
62
|
+
function createNamespacedInitArgSchema(namespace, shape) {
|
|
63
|
+
return Object.fromEntries(Object.entries(shape).map(([key, value])=>[
|
|
64
|
+
`${namespace}.${key}`,
|
|
65
|
+
value
|
|
66
|
+
]));
|
|
67
|
+
}
|
|
68
|
+
exports.createNamespacedInitArgSchema = __webpack_exports__.createNamespacedInitArgSchema;
|
|
69
|
+
exports.extractNamespacedArgs = __webpack_exports__.extractNamespacedArgs;
|
|
70
|
+
exports.sanitizeNamespacedArgs = __webpack_exports__.sanitizeNamespacedArgs;
|
|
71
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
72
|
+
"createNamespacedInitArgSchema",
|
|
73
|
+
"extractNamespacedArgs",
|
|
74
|
+
"sanitizeNamespacedArgs"
|
|
75
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
76
|
+
Object.defineProperty(exports, '__esModule', {
|
|
77
|
+
value: true
|
|
78
|
+
});
|