@midscene/shared 1.7.5-beta-20260420052829.0 → 1.7.5-beta-20260420061332.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 +9 -113
- package/dist/es/mcp/base-tools.mjs +2 -45
- package/dist/es/mcp/index.mjs +0 -1
- package/dist/es/mcp/tool-generator.mjs +11 -29
- package/dist/lib/cli/cli-runner.js +9 -113
- package/dist/lib/mcp/base-tools.js +2 -45
- package/dist/lib/mcp/index.js +12 -19
- package/dist/lib/mcp/tool-generator.js +11 -29
- package/dist/types/cli/cli-runner.d.ts +1 -3
- package/dist/types/mcp/base-tools.d.ts +5 -65
- package/dist/types/mcp/index.d.ts +0 -1
- package/dist/types/mcp/tool-generator.d.ts +3 -3
- package/dist/types/mcp/types.d.ts +0 -8
- package/package.json +1 -1
- package/src/cli/cli-runner.ts +12 -214
- package/src/mcp/base-tools.ts +9 -164
- package/src/mcp/index.ts +0 -1
- package/src/mcp/tool-generator.ts +10 -47
- package/src/mcp/types.ts +0 -10
- package/dist/es/key-alias-utils.mjs +0 -19
- package/dist/es/mcp/init-arg-utils.mjs +0 -38
- package/dist/lib/key-alias-utils.js +0 -62
- package/dist/lib/mcp/init-arg-utils.js +0 -78
- package/dist/types/key-alias-utils.d.ts +0 -9
- package/dist/types/mcp/init-arg-utils.d.ts +0 -13
- package/src/key-alias-utils.ts +0 -23
- package/src/mcp/init-arg-utils.ts +0 -105
|
@@ -2,8 +2,6 @@ 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 { z } from "zod";
|
|
6
|
-
import { getKeyAliases, isRecord } from "../key-alias-utils.mjs";
|
|
7
5
|
import { getDebug } from "../logger.mjs";
|
|
8
6
|
function _define_property(obj, key, value) {
|
|
9
7
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -28,48 +26,19 @@ function parseValue(raw) {
|
|
|
28
26
|
if (/^-?\d+(\.\d+)?$/.test(raw)) return Number(raw);
|
|
29
27
|
return raw;
|
|
30
28
|
}
|
|
31
|
-
function
|
|
29
|
+
function parseCliArgs(args) {
|
|
30
|
+
const result = {};
|
|
32
31
|
for(let i = 0; i < args.length; i++){
|
|
33
32
|
const arg = args[i];
|
|
34
33
|
if (!arg.startsWith('--')) continue;
|
|
35
34
|
const body = arg.slice(2);
|
|
36
35
|
const eqIdx = body.indexOf('=');
|
|
37
|
-
if (eqIdx >= 0)
|
|
36
|
+
if (eqIdx >= 0) result[body.slice(0, eqIdx)] = parseValue(body.slice(eqIdx + 1));
|
|
38
37
|
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
39
38
|
i++;
|
|
40
|
-
|
|
41
|
-
} else
|
|
39
|
+
result[body] = parseValue(args[i]);
|
|
40
|
+
} else result[body] = true;
|
|
42
41
|
}
|
|
43
|
-
}
|
|
44
|
-
function parseRawCliArgs(args) {
|
|
45
|
-
const result = {};
|
|
46
|
-
walkCliArgs(args, (key, value)=>{
|
|
47
|
-
result[key] = value;
|
|
48
|
-
});
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
function parseCliArgs(args) {
|
|
52
|
-
const result = {};
|
|
53
|
-
walkCliArgs(args, (key, value)=>{
|
|
54
|
-
if (!key.includes('.')) {
|
|
55
|
-
result[key] = value;
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const segments = key.split('.');
|
|
59
|
-
let current = result;
|
|
60
|
-
for (const segment of segments.slice(0, -1)){
|
|
61
|
-
const aliases = getKeyAliases(segment);
|
|
62
|
-
const existing = aliases.map((alias)=>current[alias]);
|
|
63
|
-
const nestedRecord = existing.find(isRecord);
|
|
64
|
-
const conflictingScalar = existing.find((entry)=>void 0 !== entry && !isRecord(entry));
|
|
65
|
-
if (void 0 !== conflictingScalar) throw new CLIError(`Conflicting CLI args: "${segment}" is used both as a value and as a namespace`);
|
|
66
|
-
const target = nestedRecord ?? {};
|
|
67
|
-
for (const alias of aliases)current[alias] = target;
|
|
68
|
-
current = target;
|
|
69
|
-
}
|
|
70
|
-
const leafSegment = segments[segments.length - 1];
|
|
71
|
-
for (const alias of getKeyAliases(leafSegment))current[alias] = value;
|
|
72
|
-
});
|
|
73
42
|
return result;
|
|
74
43
|
}
|
|
75
44
|
function outputContentItem(item, isError) {
|
|
@@ -97,86 +66,16 @@ function removePrefix(name, prefix) {
|
|
|
97
66
|
if (prefix && name.startsWith(prefix)) return name.slice(prefix.length);
|
|
98
67
|
return name;
|
|
99
68
|
}
|
|
100
|
-
function formatCliOptionName(name) {
|
|
101
|
-
return `--${name}`;
|
|
102
|
-
}
|
|
103
|
-
function getCliOptionDisplay(key, cliOption) {
|
|
104
|
-
const label = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
105
|
-
const aliases = [
|
|
106
|
-
...new Set(cliOption?.aliases ?? [])
|
|
107
|
-
].map((alias)=>formatCliOptionName(alias)).filter((alias)=>alias !== label);
|
|
108
|
-
return {
|
|
109
|
-
label,
|
|
110
|
-
aliases
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function getAcceptedCliOptionNames(key, cliOption) {
|
|
114
|
-
return [
|
|
115
|
-
...new Set(cliOption ? [
|
|
116
|
-
cliOption.preferredName ?? key,
|
|
117
|
-
...cliOption.aliases ?? []
|
|
118
|
-
] : [
|
|
119
|
-
key,
|
|
120
|
-
...getKeyAliases(key)
|
|
121
|
-
])
|
|
122
|
-
];
|
|
123
|
-
}
|
|
124
|
-
function toOptionalCliSchemaField(field) {
|
|
125
|
-
if ('object' == typeof field && null !== field && 'function' == typeof field.optional) return field.optional();
|
|
126
|
-
const description = 'object' == typeof field && null !== field && "description" in field && 'string' == typeof field.description ? field.description : void 0;
|
|
127
|
-
return description ? z.any().describe(description) : z.any();
|
|
128
|
-
}
|
|
129
|
-
function buildCliArgSchema(def) {
|
|
130
|
-
return Object.fromEntries(Object.entries(def.schema).flatMap(([key, zodType])=>getAcceptedCliOptionNames(key, def.cli?.options?.[key]).map((cliKey)=>[
|
|
131
|
-
cliKey,
|
|
132
|
-
toOptionalCliSchemaField(zodType)
|
|
133
|
-
])));
|
|
134
|
-
}
|
|
135
|
-
function buildDisallowedCliSpellings(def) {
|
|
136
|
-
const disallowedSpellings = new Map();
|
|
137
|
-
for (const [key] of Object.entries(def.schema)){
|
|
138
|
-
const cliOption = def.cli?.options?.[key];
|
|
139
|
-
const preferredLabel = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
140
|
-
const acceptedNames = new Set(getAcceptedCliOptionNames(key, cliOption));
|
|
141
|
-
const knownSpellings = new Set([
|
|
142
|
-
key,
|
|
143
|
-
...getKeyAliases(key),
|
|
144
|
-
...cliOption?.preferredName ? getKeyAliases(cliOption.preferredName) : [],
|
|
145
|
-
...cliOption?.aliases ?? []
|
|
146
|
-
]);
|
|
147
|
-
for (const spelling of knownSpellings)if (!acceptedNames.has(spelling)) disallowedSpellings.set(spelling, preferredLabel);
|
|
148
|
-
}
|
|
149
|
-
return disallowedSpellings;
|
|
150
|
-
}
|
|
151
|
-
function formatCliValidationError(scriptName, commandName, def, rawArgs) {
|
|
152
|
-
if (0 === Object.keys(def.schema).length) return;
|
|
153
|
-
const cliSchema = z.object(buildCliArgSchema(def)).strict();
|
|
154
|
-
const parsed = cliSchema.safeParse(rawArgs);
|
|
155
|
-
if (parsed.success) return;
|
|
156
|
-
const disallowedSpellings = buildDisallowedCliSpellings(def);
|
|
157
|
-
const unknownKeys = parsed.error.issues.flatMap((issue)=>'unrecognized_keys' === issue.code ? issue.keys : []);
|
|
158
|
-
if (unknownKeys.length > 0) return unknownKeys.map((key)=>{
|
|
159
|
-
const preferredLabel = disallowedSpellings.get(key);
|
|
160
|
-
if (preferredLabel) return `Unsupported option "--${key}" for ${scriptName} ${commandName}. Use "${preferredLabel}" instead.`;
|
|
161
|
-
return `Unknown option "--${key}" for ${scriptName} ${commandName}.`;
|
|
162
|
-
}).join('\n');
|
|
163
|
-
const [issue] = parsed.error.issues;
|
|
164
|
-
const optionName = 'string' == typeof issue?.path[0] ? `--${issue.path[0]}` : 'CLI arguments';
|
|
165
|
-
return `Invalid value for "${optionName}" in ${scriptName} ${commandName}: ${issue?.message ?? parsed.error.message}`;
|
|
166
|
-
}
|
|
167
69
|
function printCommandHelp(scriptName, cmd) {
|
|
168
70
|
const { def } = cmd;
|
|
169
71
|
console.log(`\nUsage: ${scriptName} ${cmd.name} [options]\n`);
|
|
170
72
|
console.log(def.description);
|
|
171
73
|
const schemaEntries = Object.entries(def.schema);
|
|
172
74
|
if (schemaEntries.length > 0) {
|
|
173
|
-
const optionWidth = Math.max(22, ...schemaEntries.map(([key])=>getCliOptionDisplay(key, def.cli?.options?.[key]).label.length));
|
|
174
75
|
console.log('\nOptions:');
|
|
175
76
|
for (const [key, zodType] of schemaEntries){
|
|
176
|
-
const { label, aliases } = getCliOptionDisplay(key, def.cli?.options?.[key]);
|
|
177
77
|
const desc = zodType.description ?? '';
|
|
178
|
-
|
|
179
|
-
console.log(` ${label.padEnd(optionWidth)} ${desc}${aliasText}`);
|
|
78
|
+
console.log(` --${key.padEnd(20)} ${desc}`);
|
|
180
79
|
}
|
|
181
80
|
}
|
|
182
81
|
}
|
|
@@ -237,16 +136,13 @@ async function runToolsCLI(tools, scriptName, options) {
|
|
|
237
136
|
printHelp(scriptName, commands, cliVersion);
|
|
238
137
|
throw new CLIError(`Unknown command: ${commandName}`);
|
|
239
138
|
}
|
|
240
|
-
const
|
|
241
|
-
|
|
139
|
+
const parsedArgs = parseCliArgs(restArgs);
|
|
140
|
+
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
141
|
+
if (true === parsedArgs.help) {
|
|
242
142
|
debug('showing command help for: %s', match.name);
|
|
243
143
|
printCommandHelp(scriptName, match);
|
|
244
144
|
return;
|
|
245
145
|
}
|
|
246
|
-
const cliValidationError = formatCliValidationError(scriptName, match.name, match.def, rawCliArgs);
|
|
247
|
-
if (cliValidationError) throw new CLIError(cliValidationError);
|
|
248
|
-
const parsedArgs = parseCliArgs(restArgs);
|
|
249
|
-
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
250
146
|
const result = await match.def.handler(parsedArgs);
|
|
251
147
|
debug('command %s completed, isError: %s', match.name, result.isError ?? false);
|
|
252
148
|
outputResult(result);
|
|
@@ -1,7 +1,5 @@
|
|
|
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";
|
|
5
3
|
import { generateCommonTools, generateToolsFromActionSpace } from "./tool-generator.mjs";
|
|
6
4
|
function _define_property(obj, key, value) {
|
|
7
5
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -15,47 +13,6 @@ function _define_property(obj, key, value) {
|
|
|
15
13
|
}
|
|
16
14
|
const debug = getDebug('mcp:base-tools');
|
|
17
15
|
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 acceptedNames = new Set([
|
|
41
|
-
preferredName,
|
|
42
|
-
...this.initArgSpec.cli?.preferBareKeys ? getKeyAliases(key) : getKeyAliases(canonicalKey)
|
|
43
|
-
]);
|
|
44
|
-
acceptedNames.delete(preferredName);
|
|
45
|
-
return [
|
|
46
|
-
canonicalKey,
|
|
47
|
-
{
|
|
48
|
-
preferredName,
|
|
49
|
-
aliases: [
|
|
50
|
-
...acceptedNames
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
];
|
|
54
|
-
}));
|
|
55
|
-
return {
|
|
56
|
-
options
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
16
|
preparePlatformTools() {
|
|
60
17
|
return [];
|
|
61
18
|
}
|
|
@@ -73,8 +30,8 @@ class BaseMidsceneTools {
|
|
|
73
30
|
await tempDevice.destroy?.();
|
|
74
31
|
debug('Action space from temporary device:', actionSpace.map((a)=>a.name).join(', '));
|
|
75
32
|
}
|
|
76
|
-
const actionTools = generateToolsFromActionSpace(actionSpace, (
|
|
77
|
-
const commonTools = generateCommonTools((
|
|
33
|
+
const actionTools = generateToolsFromActionSpace(actionSpace, ()=>this.ensureAgent());
|
|
34
|
+
const commonTools = generateCommonTools(()=>this.ensureAgent());
|
|
78
35
|
this.toolDefinitions.push(...actionTools, ...commonTools);
|
|
79
36
|
debug('Total tools prepared:', this.toolDefinitions.length);
|
|
80
37
|
}
|
package/dist/es/mcp/index.mjs
CHANGED
|
@@ -277,30 +277,17 @@ async function captureFailureResult(agent, actionName, errorMessage) {
|
|
|
277
277
|
};
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
|
-
function
|
|
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) {
|
|
280
|
+
function generateToolsFromActionSpace(actionSpace, getAgent) {
|
|
290
281
|
return actionSpace.map((action)=>{
|
|
291
|
-
const schema =
|
|
292
|
-
...extractActionSchema(action.paramSchema),
|
|
293
|
-
...initArgSchema
|
|
294
|
-
};
|
|
282
|
+
const schema = extractActionSchema(action.paramSchema);
|
|
295
283
|
return {
|
|
296
284
|
name: action.name,
|
|
297
285
|
description: describeActionForMCP(action),
|
|
298
286
|
schema,
|
|
299
|
-
cli: initArgCliMetadata,
|
|
300
287
|
handler: async (args)=>{
|
|
301
288
|
try {
|
|
302
|
-
const agent = await getAgent(
|
|
303
|
-
const normalizedArgs = normalizeActionArgs(
|
|
289
|
+
const agent = await getAgent();
|
|
290
|
+
const normalizedArgs = normalizeActionArgs(args, action.paramSchema);
|
|
304
291
|
let actionResult;
|
|
305
292
|
try {
|
|
306
293
|
actionResult = await executeAction(agent, action.name, normalizedArgs);
|
|
@@ -319,18 +306,15 @@ function generateToolsFromActionSpace(actionSpace, getAgent, sanitizeArgs = (arg
|
|
|
319
306
|
};
|
|
320
307
|
});
|
|
321
308
|
}
|
|
322
|
-
function generateCommonTools(getAgent
|
|
309
|
+
function generateCommonTools(getAgent) {
|
|
323
310
|
return [
|
|
324
311
|
{
|
|
325
312
|
name: 'take_screenshot',
|
|
326
313
|
description: 'Capture screenshot of current page/screen',
|
|
327
|
-
schema: {
|
|
328
|
-
|
|
329
|
-
},
|
|
330
|
-
cli: initArgCliMetadata,
|
|
331
|
-
handler: async (args = {})=>{
|
|
314
|
+
schema: {},
|
|
315
|
+
handler: async ()=>{
|
|
332
316
|
try {
|
|
333
|
-
const agent = await getAgent(
|
|
317
|
+
const agent = await getAgent();
|
|
334
318
|
const screenshot = await agent.page?.screenshotBase64();
|
|
335
319
|
if (!screenshot) return createErrorResult('Screenshot not available');
|
|
336
320
|
const { mimeType, body } = parseBase64(screenshot);
|
|
@@ -354,14 +338,12 @@ function generateCommonTools(getAgent, initArgSchema = {}, initArgCliMetadata) {
|
|
|
354
338
|
name: 'act',
|
|
355
339
|
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.',
|
|
356
340
|
schema: {
|
|
357
|
-
prompt: z.string().describe('Natural language description of the action to perform, e.g. "press Command+Space, type Safari, press Enter"')
|
|
358
|
-
...initArgSchema
|
|
341
|
+
prompt: z.string().describe('Natural language description of the action to perform, e.g. "press Command+Space, type Safari, press Enter"')
|
|
359
342
|
},
|
|
360
|
-
|
|
361
|
-
handler: async (args = {})=>{
|
|
343
|
+
handler: async (args)=>{
|
|
362
344
|
const prompt = args.prompt;
|
|
363
345
|
try {
|
|
364
|
-
const agent = await getAgent(
|
|
346
|
+
const agent = await getAgent();
|
|
365
347
|
if (!agent.aiAction) return createErrorResult('act is not supported by this agent');
|
|
366
348
|
const result = await agent.aiAction(prompt, {
|
|
367
349
|
deepThink: false
|
|
@@ -44,8 +44,6 @@ 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_zod_namespaceObject = require("zod");
|
|
48
|
-
const external_key_alias_utils_js_namespaceObject = require("../key-alias-utils.js");
|
|
49
47
|
const external_logger_js_namespaceObject = require("../logger.js");
|
|
50
48
|
function _define_property(obj, key, value) {
|
|
51
49
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -70,48 +68,19 @@ function parseValue(raw) {
|
|
|
70
68
|
if (/^-?\d+(\.\d+)?$/.test(raw)) return Number(raw);
|
|
71
69
|
return raw;
|
|
72
70
|
}
|
|
73
|
-
function
|
|
71
|
+
function parseCliArgs(args) {
|
|
72
|
+
const result = {};
|
|
74
73
|
for(let i = 0; i < args.length; i++){
|
|
75
74
|
const arg = args[i];
|
|
76
75
|
if (!arg.startsWith('--')) continue;
|
|
77
76
|
const body = arg.slice(2);
|
|
78
77
|
const eqIdx = body.indexOf('=');
|
|
79
|
-
if (eqIdx >= 0)
|
|
78
|
+
if (eqIdx >= 0) result[body.slice(0, eqIdx)] = parseValue(body.slice(eqIdx + 1));
|
|
80
79
|
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
81
80
|
i++;
|
|
82
|
-
|
|
83
|
-
} else
|
|
81
|
+
result[body] = parseValue(args[i]);
|
|
82
|
+
} else result[body] = true;
|
|
84
83
|
}
|
|
85
|
-
}
|
|
86
|
-
function parseRawCliArgs(args) {
|
|
87
|
-
const result = {};
|
|
88
|
-
walkCliArgs(args, (key, value)=>{
|
|
89
|
-
result[key] = value;
|
|
90
|
-
});
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
function parseCliArgs(args) {
|
|
94
|
-
const result = {};
|
|
95
|
-
walkCliArgs(args, (key, value)=>{
|
|
96
|
-
if (!key.includes('.')) {
|
|
97
|
-
result[key] = value;
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const segments = key.split('.');
|
|
101
|
-
let current = result;
|
|
102
|
-
for (const segment of segments.slice(0, -1)){
|
|
103
|
-
const aliases = (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(segment);
|
|
104
|
-
const existing = aliases.map((alias)=>current[alias]);
|
|
105
|
-
const nestedRecord = existing.find(external_key_alias_utils_js_namespaceObject.isRecord);
|
|
106
|
-
const conflictingScalar = existing.find((entry)=>void 0 !== entry && !(0, external_key_alias_utils_js_namespaceObject.isRecord)(entry));
|
|
107
|
-
if (void 0 !== conflictingScalar) throw new CLIError(`Conflicting CLI args: "${segment}" is used both as a value and as a namespace`);
|
|
108
|
-
const target = nestedRecord ?? {};
|
|
109
|
-
for (const alias of aliases)current[alias] = target;
|
|
110
|
-
current = target;
|
|
111
|
-
}
|
|
112
|
-
const leafSegment = segments[segments.length - 1];
|
|
113
|
-
for (const alias of (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(leafSegment))current[alias] = value;
|
|
114
|
-
});
|
|
115
84
|
return result;
|
|
116
85
|
}
|
|
117
86
|
function outputContentItem(item, isError) {
|
|
@@ -139,86 +108,16 @@ function removePrefix(name, prefix) {
|
|
|
139
108
|
if (prefix && name.startsWith(prefix)) return name.slice(prefix.length);
|
|
140
109
|
return name;
|
|
141
110
|
}
|
|
142
|
-
function formatCliOptionName(name) {
|
|
143
|
-
return `--${name}`;
|
|
144
|
-
}
|
|
145
|
-
function getCliOptionDisplay(key, cliOption) {
|
|
146
|
-
const label = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
147
|
-
const aliases = [
|
|
148
|
-
...new Set(cliOption?.aliases ?? [])
|
|
149
|
-
].map((alias)=>formatCliOptionName(alias)).filter((alias)=>alias !== label);
|
|
150
|
-
return {
|
|
151
|
-
label,
|
|
152
|
-
aliases
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function getAcceptedCliOptionNames(key, cliOption) {
|
|
156
|
-
return [
|
|
157
|
-
...new Set(cliOption ? [
|
|
158
|
-
cliOption.preferredName ?? key,
|
|
159
|
-
...cliOption.aliases ?? []
|
|
160
|
-
] : [
|
|
161
|
-
key,
|
|
162
|
-
...(0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(key)
|
|
163
|
-
])
|
|
164
|
-
];
|
|
165
|
-
}
|
|
166
|
-
function toOptionalCliSchemaField(field) {
|
|
167
|
-
if ('object' == typeof field && null !== field && 'function' == typeof field.optional) return field.optional();
|
|
168
|
-
const description = 'object' == typeof field && null !== field && "description" in field && 'string' == typeof field.description ? field.description : void 0;
|
|
169
|
-
return description ? external_zod_namespaceObject.z.any().describe(description) : external_zod_namespaceObject.z.any();
|
|
170
|
-
}
|
|
171
|
-
function buildCliArgSchema(def) {
|
|
172
|
-
return Object.fromEntries(Object.entries(def.schema).flatMap(([key, zodType])=>getAcceptedCliOptionNames(key, def.cli?.options?.[key]).map((cliKey)=>[
|
|
173
|
-
cliKey,
|
|
174
|
-
toOptionalCliSchemaField(zodType)
|
|
175
|
-
])));
|
|
176
|
-
}
|
|
177
|
-
function buildDisallowedCliSpellings(def) {
|
|
178
|
-
const disallowedSpellings = new Map();
|
|
179
|
-
for (const [key] of Object.entries(def.schema)){
|
|
180
|
-
const cliOption = def.cli?.options?.[key];
|
|
181
|
-
const preferredLabel = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
182
|
-
const acceptedNames = new Set(getAcceptedCliOptionNames(key, cliOption));
|
|
183
|
-
const knownSpellings = new Set([
|
|
184
|
-
key,
|
|
185
|
-
...(0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(key),
|
|
186
|
-
...cliOption?.preferredName ? (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(cliOption.preferredName) : [],
|
|
187
|
-
...cliOption?.aliases ?? []
|
|
188
|
-
]);
|
|
189
|
-
for (const spelling of knownSpellings)if (!acceptedNames.has(spelling)) disallowedSpellings.set(spelling, preferredLabel);
|
|
190
|
-
}
|
|
191
|
-
return disallowedSpellings;
|
|
192
|
-
}
|
|
193
|
-
function formatCliValidationError(scriptName, commandName, def, rawArgs) {
|
|
194
|
-
if (0 === Object.keys(def.schema).length) return;
|
|
195
|
-
const cliSchema = external_zod_namespaceObject.z.object(buildCliArgSchema(def)).strict();
|
|
196
|
-
const parsed = cliSchema.safeParse(rawArgs);
|
|
197
|
-
if (parsed.success) return;
|
|
198
|
-
const disallowedSpellings = buildDisallowedCliSpellings(def);
|
|
199
|
-
const unknownKeys = parsed.error.issues.flatMap((issue)=>'unrecognized_keys' === issue.code ? issue.keys : []);
|
|
200
|
-
if (unknownKeys.length > 0) return unknownKeys.map((key)=>{
|
|
201
|
-
const preferredLabel = disallowedSpellings.get(key);
|
|
202
|
-
if (preferredLabel) return `Unsupported option "--${key}" for ${scriptName} ${commandName}. Use "${preferredLabel}" instead.`;
|
|
203
|
-
return `Unknown option "--${key}" for ${scriptName} ${commandName}.`;
|
|
204
|
-
}).join('\n');
|
|
205
|
-
const [issue] = parsed.error.issues;
|
|
206
|
-
const optionName = 'string' == typeof issue?.path[0] ? `--${issue.path[0]}` : 'CLI arguments';
|
|
207
|
-
return `Invalid value for "${optionName}" in ${scriptName} ${commandName}: ${issue?.message ?? parsed.error.message}`;
|
|
208
|
-
}
|
|
209
111
|
function printCommandHelp(scriptName, cmd) {
|
|
210
112
|
const { def } = cmd;
|
|
211
113
|
console.log(`\nUsage: ${scriptName} ${cmd.name} [options]\n`);
|
|
212
114
|
console.log(def.description);
|
|
213
115
|
const schemaEntries = Object.entries(def.schema);
|
|
214
116
|
if (schemaEntries.length > 0) {
|
|
215
|
-
const optionWidth = Math.max(22, ...schemaEntries.map(([key])=>getCliOptionDisplay(key, def.cli?.options?.[key]).label.length));
|
|
216
117
|
console.log('\nOptions:');
|
|
217
118
|
for (const [key, zodType] of schemaEntries){
|
|
218
|
-
const { label, aliases } = getCliOptionDisplay(key, def.cli?.options?.[key]);
|
|
219
119
|
const desc = zodType.description ?? '';
|
|
220
|
-
|
|
221
|
-
console.log(` ${label.padEnd(optionWidth)} ${desc}${aliasText}`);
|
|
120
|
+
console.log(` --${key.padEnd(20)} ${desc}`);
|
|
222
121
|
}
|
|
223
122
|
}
|
|
224
123
|
}
|
|
@@ -279,16 +178,13 @@ async function runToolsCLI(tools, scriptName, options) {
|
|
|
279
178
|
printHelp(scriptName, commands, cliVersion);
|
|
280
179
|
throw new CLIError(`Unknown command: ${commandName}`);
|
|
281
180
|
}
|
|
282
|
-
const
|
|
283
|
-
|
|
181
|
+
const parsedArgs = parseCliArgs(restArgs);
|
|
182
|
+
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
183
|
+
if (true === parsedArgs.help) {
|
|
284
184
|
debug('showing command help for: %s', match.name);
|
|
285
185
|
printCommandHelp(scriptName, match);
|
|
286
186
|
return;
|
|
287
187
|
}
|
|
288
|
-
const cliValidationError = formatCliValidationError(scriptName, match.name, match.def, rawCliArgs);
|
|
289
|
-
if (cliValidationError) throw new CLIError(cliValidationError);
|
|
290
|
-
const parsedArgs = parseCliArgs(restArgs);
|
|
291
|
-
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
292
188
|
const result = await match.def.handler(parsedArgs);
|
|
293
189
|
debug('command %s completed, isError: %s', match.name, result.isError ?? false);
|
|
294
190
|
outputResult(result);
|
|
@@ -28,8 +28,6 @@ __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");
|
|
33
31
|
const external_tool_generator_js_namespaceObject = require("./tool-generator.js");
|
|
34
32
|
function _define_property(obj, key, value) {
|
|
35
33
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -43,47 +41,6 @@ function _define_property(obj, key, value) {
|
|
|
43
41
|
}
|
|
44
42
|
const debug = (0, logger_namespaceObject.getDebug)('mcp:base-tools');
|
|
45
43
|
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 acceptedNames = new Set([
|
|
69
|
-
preferredName,
|
|
70
|
-
...this.initArgSpec.cli?.preferBareKeys ? (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(key) : (0, external_key_alias_utils_js_namespaceObject.getKeyAliases)(canonicalKey)
|
|
71
|
-
]);
|
|
72
|
-
acceptedNames.delete(preferredName);
|
|
73
|
-
return [
|
|
74
|
-
canonicalKey,
|
|
75
|
-
{
|
|
76
|
-
preferredName,
|
|
77
|
-
aliases: [
|
|
78
|
-
...acceptedNames
|
|
79
|
-
]
|
|
80
|
-
}
|
|
81
|
-
];
|
|
82
|
-
}));
|
|
83
|
-
return {
|
|
84
|
-
options
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
44
|
preparePlatformTools() {
|
|
88
45
|
return [];
|
|
89
46
|
}
|
|
@@ -101,8 +58,8 @@ class BaseMidsceneTools {
|
|
|
101
58
|
await tempDevice.destroy?.();
|
|
102
59
|
debug('Action space from temporary device:', actionSpace.map((a)=>a.name).join(', '));
|
|
103
60
|
}
|
|
104
|
-
const actionTools = (0, external_tool_generator_js_namespaceObject.generateToolsFromActionSpace)(actionSpace, (
|
|
105
|
-
const commonTools = (0, external_tool_generator_js_namespaceObject.generateCommonTools)((
|
|
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());
|
|
106
63
|
this.toolDefinitions.push(...actionTools, ...commonTools);
|
|
107
64
|
debug('Total tools prepared:', this.toolDefinitions.length);
|
|
108
65
|
}
|
package/dist/lib/mcp/index.js
CHANGED
|
@@ -12,9 +12,6 @@ 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
|
-
},
|
|
18
15
|
"./inject-report-html-plugin" (module) {
|
|
19
16
|
module.exports = require("./inject-report-html-plugin.js");
|
|
20
17
|
},
|
|
@@ -79,33 +76,29 @@ var __webpack_exports__ = {};
|
|
|
79
76
|
var __rspack_reexport = {};
|
|
80
77
|
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];
|
|
81
78
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
82
|
-
var
|
|
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");
|
|
79
|
+
var _error_formatter__rspack_import_2 = __webpack_require__("./error-formatter");
|
|
87
80
|
var __rspack_reexport = {};
|
|
88
|
-
for(const __rspack_import_key in
|
|
81
|
+
for(const __rspack_import_key in _error_formatter__rspack_import_2)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_error_formatter__rspack_import_2[__rspack_import_key];
|
|
89
82
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
90
|
-
var
|
|
83
|
+
var _tool_generator__rspack_import_3 = __webpack_require__("./tool-generator");
|
|
91
84
|
var __rspack_reexport = {};
|
|
92
|
-
for(const __rspack_import_key in
|
|
85
|
+
for(const __rspack_import_key in _tool_generator__rspack_import_3)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_tool_generator__rspack_import_3[__rspack_import_key];
|
|
93
86
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
94
|
-
var
|
|
87
|
+
var _types__rspack_import_4 = __webpack_require__("./types");
|
|
95
88
|
var __rspack_reexport = {};
|
|
96
|
-
for(const __rspack_import_key in
|
|
89
|
+
for(const __rspack_import_key in _types__rspack_import_4)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_types__rspack_import_4[__rspack_import_key];
|
|
97
90
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
98
|
-
var
|
|
91
|
+
var _inject_report_html_plugin__rspack_import_5 = __webpack_require__("./inject-report-html-plugin");
|
|
99
92
|
var __rspack_reexport = {};
|
|
100
|
-
for(const __rspack_import_key in
|
|
93
|
+
for(const __rspack_import_key in _inject_report_html_plugin__rspack_import_5)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_inject_report_html_plugin__rspack_import_5[__rspack_import_key];
|
|
101
94
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
102
|
-
var
|
|
95
|
+
var _launcher_helper__rspack_import_6 = __webpack_require__("./launcher-helper");
|
|
103
96
|
var __rspack_reexport = {};
|
|
104
|
-
for(const __rspack_import_key in
|
|
97
|
+
for(const __rspack_import_key in _launcher_helper__rspack_import_6)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_launcher_helper__rspack_import_6[__rspack_import_key];
|
|
105
98
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
106
|
-
var
|
|
99
|
+
var _chrome_path__rspack_import_7 = __webpack_require__("./chrome-path");
|
|
107
100
|
var __rspack_reexport = {};
|
|
108
|
-
for(const __rspack_import_key in
|
|
101
|
+
for(const __rspack_import_key in _chrome_path__rspack_import_7)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_chrome_path__rspack_import_7[__rspack_import_key];
|
|
109
102
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
110
103
|
})();
|
|
111
104
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|