@aiscene/shared 8.0.2 → 8.0.3
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-args.mjs +95 -0
- package/dist/es/cli/cli-error.mjs +24 -0
- package/dist/es/cli/cli-runner.mjs +10 -40
- package/dist/es/cli/index.mjs +4 -2
- package/dist/es/constants/example-code.mjs +2 -2
- package/dist/es/constants/index.mjs +6 -1
- package/dist/es/env/model-config-manager.mjs +3 -0
- package/dist/es/env/parse-model-config.mjs +6 -1
- package/dist/es/env/types.mjs +2 -1
- package/dist/es/env/utils.mjs +1 -9
- package/dist/es/extractor/index.mjs +2 -2
- package/dist/es/img/index.mjs +2 -2
- package/dist/es/img/info.mjs +18 -21
- package/dist/es/key-alias-utils.mjs +19 -0
- package/dist/es/mcp/base-server.mjs +10 -9
- package/dist/es/mcp/base-tools.mjs +72 -4
- package/dist/es/mcp/cli-report-session.mjs +78 -0
- package/dist/es/mcp/error-formatter.mjs +19 -0
- package/dist/es/mcp/index.mjs +2 -0
- package/dist/es/mcp/init-arg-utils.mjs +38 -0
- package/dist/es/mcp/inject-report-html-plugin.mjs +1 -1
- package/dist/es/mcp/tool-generator.mjs +65 -17
- package/dist/es/node/fs.mjs +1 -1
- package/dist/lib/cli/cli-args.js +138 -0
- package/dist/lib/cli/cli-error.js +61 -0
- package/dist/lib/cli/cli-runner.js +19 -46
- package/dist/lib/cli/index.js +8 -3
- package/dist/lib/constants/example-code.js +2 -2
- package/dist/lib/constants/index.js +23 -3
- package/dist/lib/env/model-config-manager.js +3 -0
- package/dist/lib/env/parse-model-config.js +6 -1
- package/dist/lib/env/types.js +4 -0
- package/dist/lib/env/utils.js +0 -11
- package/dist/lib/extractor/index.js +3 -0
- package/dist/lib/img/index.js +3 -0
- package/dist/lib/img/info.js +21 -21
- package/dist/lib/key-alias-utils.js +62 -0
- package/dist/lib/mcp/base-server.js +11 -10
- package/dist/lib/mcp/base-tools.js +74 -6
- package/dist/lib/mcp/cli-report-session.js +121 -0
- package/dist/lib/mcp/error-formatter.js +53 -0
- package/dist/lib/mcp/index.js +24 -10
- package/dist/lib/mcp/init-arg-utils.js +78 -0
- package/dist/lib/mcp/inject-report-html-plugin.js +1 -1
- package/dist/lib/mcp/tool-generator.js +74 -26
- package/dist/lib/node/fs.js +1 -1
- package/dist/types/cli/cli-args.d.ts +8 -0
- package/dist/types/cli/cli-error.d.ts +5 -0
- package/dist/types/cli/cli-runner.d.ts +4 -7
- package/dist/types/cli/index.d.ts +3 -1
- package/dist/types/constants/example-code.d.ts +1 -1
- package/dist/types/constants/index.d.ts +5 -0
- package/dist/types/env/types.d.ts +10 -2
- package/dist/types/env/utils.d.ts +0 -31
- package/dist/types/extractor/index.d.ts +1 -1
- package/dist/types/img/index.d.ts +1 -1
- package/dist/types/img/info.d.ts +5 -0
- package/dist/types/key-alias-utils.d.ts +9 -0
- package/dist/types/mcp/base-tools.d.ts +74 -5
- package/dist/types/mcp/cli-report-session.d.ts +12 -0
- package/dist/types/mcp/error-formatter.d.ts +12 -0
- package/dist/types/mcp/index.d.ts +2 -0
- package/dist/types/mcp/init-arg-utils.d.ts +13 -0
- package/dist/types/mcp/inject-report-html-plugin.d.ts +2 -2
- package/dist/types/mcp/launcher-helper.d.ts +3 -3
- package/dist/types/mcp/tool-generator.d.ts +3 -3
- package/dist/types/mcp/types.d.ts +9 -0
- package/package.json +1 -1
- package/src/cli/cli-args.ts +173 -0
- package/src/cli/cli-error.ts +24 -0
- package/src/cli/cli-runner.ts +37 -56
- package/src/cli/index.ts +3 -7
- package/src/constants/example-code.ts +2 -2
- package/src/constants/index.ts +10 -0
- package/src/env/model-config-manager.ts +3 -0
- package/src/env/parse-model-config.ts +19 -1
- package/src/env/types.ts +11 -2
- package/src/env/utils.ts +0 -50
- package/src/extractor/index.ts +1 -1
- package/src/img/index.ts +2 -0
- package/src/img/info.ts +36 -45
- package/src/key-alias-utils.ts +23 -0
- package/src/mcp/base-server.ts +10 -12
- package/src/mcp/base-tools.ts +218 -11
- package/src/mcp/cli-report-session.ts +130 -0
- package/src/mcp/error-formatter.ts +52 -0
- package/src/mcp/index.ts +2 -0
- package/src/mcp/init-arg-utils.ts +105 -0
- package/src/mcp/inject-report-html-plugin.ts +3 -3
- package/src/mcp/launcher-helper.ts +3 -3
- package/src/mcp/tool-generator.ts +98 -20
- package/src/mcp/types.ts +16 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getKeyAliases } from "../key-alias-utils.mjs";
|
|
3
|
+
function parseValue(raw) {
|
|
4
|
+
if (raw.startsWith('{') || raw.startsWith('[')) try {
|
|
5
|
+
return JSON.parse(raw);
|
|
6
|
+
} catch {}
|
|
7
|
+
if (/^-?\d+(\.\d+)?$/.test(raw)) return Number(raw);
|
|
8
|
+
return raw;
|
|
9
|
+
}
|
|
10
|
+
function walkCliArgs(args, setArgValue) {
|
|
11
|
+
for(let i = 0; i < args.length; i++){
|
|
12
|
+
const arg = args[i];
|
|
13
|
+
if (!arg.startsWith('--')) continue;
|
|
14
|
+
const body = arg.slice(2);
|
|
15
|
+
const eqIdx = body.indexOf('=');
|
|
16
|
+
if (eqIdx >= 0) setArgValue(body.slice(0, eqIdx), parseValue(body.slice(eqIdx + 1)));
|
|
17
|
+
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
18
|
+
i++;
|
|
19
|
+
setArgValue(body, parseValue(args[i]));
|
|
20
|
+
} else setArgValue(body, true);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function parseCliArgs(args) {
|
|
24
|
+
const result = {};
|
|
25
|
+
walkCliArgs(args, (key, value)=>{
|
|
26
|
+
result[key] = value;
|
|
27
|
+
});
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
function formatCliOptionName(name) {
|
|
31
|
+
return `--${name}`;
|
|
32
|
+
}
|
|
33
|
+
function getCliOptionDisplay(key, cliOption) {
|
|
34
|
+
const label = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
35
|
+
const aliases = [
|
|
36
|
+
...new Set(cliOption?.aliases ?? [])
|
|
37
|
+
].map((alias)=>formatCliOptionName(alias)).filter((alias)=>alias !== label);
|
|
38
|
+
return {
|
|
39
|
+
label,
|
|
40
|
+
aliases
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function getAcceptedCliOptionNames(key, cliOption) {
|
|
44
|
+
return [
|
|
45
|
+
...new Set(cliOption ? [
|
|
46
|
+
cliOption.preferredName ?? key,
|
|
47
|
+
...cliOption.aliases ?? []
|
|
48
|
+
] : [
|
|
49
|
+
key,
|
|
50
|
+
...getKeyAliases(key)
|
|
51
|
+
])
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
function toOptionalCliSchemaField(field) {
|
|
55
|
+
if ('object' == typeof field && null !== field && 'function' == typeof field.optional) return field.optional();
|
|
56
|
+
const description = 'object' == typeof field && null !== field && "description" in field && 'string' == typeof field.description ? field.description : void 0;
|
|
57
|
+
return description ? z.any().describe(description) : z.any();
|
|
58
|
+
}
|
|
59
|
+
function buildCliArgSchema(def) {
|
|
60
|
+
return Object.fromEntries(Object.entries(def.schema).flatMap(([key, zodType])=>getAcceptedCliOptionNames(key, def.cli?.options?.[key]).map((cliKey)=>[
|
|
61
|
+
cliKey,
|
|
62
|
+
toOptionalCliSchemaField(zodType)
|
|
63
|
+
])));
|
|
64
|
+
}
|
|
65
|
+
function buildDisallowedCliSpellings(def) {
|
|
66
|
+
const disallowedSpellings = new Set();
|
|
67
|
+
for (const [key] of Object.entries(def.schema)){
|
|
68
|
+
const cliOption = def.cli?.options?.[key];
|
|
69
|
+
const acceptedNames = new Set(getAcceptedCliOptionNames(key, cliOption));
|
|
70
|
+
const knownSpellings = new Set([
|
|
71
|
+
key,
|
|
72
|
+
...getKeyAliases(key),
|
|
73
|
+
...cliOption?.preferredName ? getKeyAliases(cliOption.preferredName) : [],
|
|
74
|
+
...cliOption?.aliases ?? []
|
|
75
|
+
]);
|
|
76
|
+
for (const spelling of knownSpellings)if (!acceptedNames.has(spelling)) disallowedSpellings.add(spelling);
|
|
77
|
+
}
|
|
78
|
+
return disallowedSpellings;
|
|
79
|
+
}
|
|
80
|
+
function formatCliValidationError(scriptName, commandName, def, rawArgs) {
|
|
81
|
+
if (0 === Object.keys(def.schema).length) return;
|
|
82
|
+
const cliSchema = z.object(buildCliArgSchema(def)).strict();
|
|
83
|
+
const parsed = cliSchema.safeParse(rawArgs);
|
|
84
|
+
if (parsed.success) return;
|
|
85
|
+
const disallowedSpellings = buildDisallowedCliSpellings(def);
|
|
86
|
+
const unknownKeys = parsed.error.issues.flatMap((issue)=>'unrecognized_keys' === issue.code ? issue.keys : []);
|
|
87
|
+
if (unknownKeys.length > 0) return unknownKeys.map((key)=>{
|
|
88
|
+
if (disallowedSpellings.has(key)) return `Unsupported option "--${key}" for ${scriptName} ${commandName}.`;
|
|
89
|
+
return `Unknown option "--${key}" for ${scriptName} ${commandName}.`;
|
|
90
|
+
}).join('\n');
|
|
91
|
+
const [issue] = parsed.error.issues;
|
|
92
|
+
const optionName = 'string' == typeof issue?.path[0] ? `--${issue.path[0]}` : 'CLI arguments';
|
|
93
|
+
return `Invalid value for "${optionName}" in ${scriptName} ${commandName}: ${issue?.message ?? parsed.error.message}`;
|
|
94
|
+
}
|
|
95
|
+
export { formatCliValidationError, getCliOptionDisplay, parseCliArgs, parseValue };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
3
|
+
value: value,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true
|
|
7
|
+
});
|
|
8
|
+
else obj[key] = value;
|
|
9
|
+
return obj;
|
|
10
|
+
}
|
|
11
|
+
class CLIError extends Error {
|
|
12
|
+
constructor(message, exitCode = 1){
|
|
13
|
+
super(message), _define_property(this, "exitCode", void 0), this.exitCode = exitCode;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function reportCLIError(error, log = console.error) {
|
|
17
|
+
if (error instanceof CLIError) {
|
|
18
|
+
log(error.message);
|
|
19
|
+
return error.exitCode;
|
|
20
|
+
}
|
|
21
|
+
log(error);
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
export { CLIError, reportCLIError };
|
|
@@ -3,44 +3,9 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import dotenv from "dotenv";
|
|
5
5
|
import { getDebug } from "../logger.mjs";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
value: value,
|
|
9
|
-
enumerable: true,
|
|
10
|
-
configurable: true,
|
|
11
|
-
writable: true
|
|
12
|
-
});
|
|
13
|
-
else obj[key] = value;
|
|
14
|
-
return obj;
|
|
15
|
-
}
|
|
6
|
+
import { formatCliValidationError, getCliOptionDisplay, parseCliArgs, parseValue } from "./cli-args.mjs";
|
|
7
|
+
import { CLIError, reportCLIError } from "./cli-error.mjs";
|
|
16
8
|
const debug = getDebug('cli-runner');
|
|
17
|
-
class CLIError extends Error {
|
|
18
|
-
constructor(message, exitCode = 1){
|
|
19
|
-
super(message), _define_property(this, "exitCode", void 0), this.exitCode = exitCode;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function parseValue(raw) {
|
|
23
|
-
if (raw.startsWith('{') || raw.startsWith('[')) try {
|
|
24
|
-
return JSON.parse(raw);
|
|
25
|
-
} catch {}
|
|
26
|
-
if (/^-?\d+(\.\d+)?$/.test(raw)) return Number(raw);
|
|
27
|
-
return raw;
|
|
28
|
-
}
|
|
29
|
-
function parseCliArgs(args) {
|
|
30
|
-
const result = {};
|
|
31
|
-
for(let i = 0; i < args.length; i++){
|
|
32
|
-
const arg = args[i];
|
|
33
|
-
if (!arg.startsWith('--')) continue;
|
|
34
|
-
const body = arg.slice(2);
|
|
35
|
-
const eqIdx = body.indexOf('=');
|
|
36
|
-
if (eqIdx >= 0) result[body.slice(0, eqIdx)] = parseValue(body.slice(eqIdx + 1));
|
|
37
|
-
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
38
|
-
i++;
|
|
39
|
-
result[body] = parseValue(args[i]);
|
|
40
|
-
} else result[body] = true;
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
44
9
|
function outputContentItem(item, isError) {
|
|
45
10
|
switch(item.type){
|
|
46
11
|
case 'text':
|
|
@@ -72,10 +37,13 @@ function printCommandHelp(scriptName, cmd) {
|
|
|
72
37
|
console.log(def.description);
|
|
73
38
|
const schemaEntries = Object.entries(def.schema);
|
|
74
39
|
if (schemaEntries.length > 0) {
|
|
40
|
+
const optionWidth = Math.max(22, ...schemaEntries.map(([key])=>getCliOptionDisplay(key, def.cli?.options?.[key]).label.length));
|
|
75
41
|
console.log('\nOptions:');
|
|
76
42
|
for (const [key, zodType] of schemaEntries){
|
|
43
|
+
const { label, aliases } = getCliOptionDisplay(key, def.cli?.options?.[key]);
|
|
77
44
|
const desc = zodType.description ?? '';
|
|
78
|
-
|
|
45
|
+
const aliasText = aliases.length > 0 ? ` (aliases: ${aliases.join(', ')})` : '';
|
|
46
|
+
console.log(` ${label.padEnd(optionWidth)} ${desc}${aliasText}`);
|
|
79
47
|
}
|
|
80
48
|
}
|
|
81
49
|
}
|
|
@@ -137,16 +105,18 @@ async function runToolsCLI(tools, scriptName, options) {
|
|
|
137
105
|
throw new CLIError(`Unknown command: ${commandName}`);
|
|
138
106
|
}
|
|
139
107
|
const parsedArgs = parseCliArgs(restArgs);
|
|
140
|
-
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
141
108
|
if (true === parsedArgs.help) {
|
|
142
109
|
debug('showing command help for: %s', match.name);
|
|
143
110
|
printCommandHelp(scriptName, match);
|
|
144
111
|
return;
|
|
145
112
|
}
|
|
113
|
+
const cliValidationError = formatCliValidationError(scriptName, match.name, match.def, parsedArgs);
|
|
114
|
+
if (cliValidationError) throw new CLIError(cliValidationError);
|
|
115
|
+
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
146
116
|
const result = await match.def.handler(parsedArgs);
|
|
147
117
|
debug('command %s completed, isError: %s', match.name, result.isError ?? false);
|
|
148
118
|
outputResult(result);
|
|
149
119
|
await tools.destroy();
|
|
150
120
|
if (result.isError) throw new CLIError('Command failed', 1);
|
|
151
121
|
}
|
|
152
|
-
export { CLIError, parseCliArgs, parseValue, removePrefix, runToolsCLI };
|
|
122
|
+
export { CLIError, parseCliArgs, parseValue, removePrefix, reportCLIError, runToolsCLI };
|
package/dist/es/cli/index.mjs
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import { CLIError,
|
|
2
|
-
|
|
1
|
+
import { CLIError, reportCLIError } from "./cli-error.mjs";
|
|
2
|
+
import { parseCliArgs, parseValue } from "./cli-args.mjs";
|
|
3
|
+
import { removePrefix, runToolsCLI } from "./cli-runner.mjs";
|
|
4
|
+
export { CLIError, parseCliArgs, parseValue, removePrefix, reportCLIError, runToolsCLI };
|
|
@@ -28,8 +28,8 @@ aiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data fro
|
|
|
28
28
|
// The following is test code for Midscene AI, for reference
|
|
29
29
|
// The following is Playwright syntax, you can use Playwright to assist in test generation
|
|
30
30
|
import { test as base } from '@playwright/test';
|
|
31
|
-
import type { PlayWrightAiFixtureType } from '@
|
|
32
|
-
import { PlaywrightAiFixture } from '@
|
|
31
|
+
import type { PlayWrightAiFixtureType } from '@aiscene/web/playwright';
|
|
32
|
+
import { PlaywrightAiFixture } from '@aiscene/web/playwright';
|
|
33
33
|
|
|
34
34
|
const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({
|
|
35
35
|
waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms
|
|
@@ -15,9 +15,14 @@ var constants_NodeType = /*#__PURE__*/ function(NodeType) {
|
|
|
15
15
|
}({});
|
|
16
16
|
const PLAYGROUND_SERVER_PORT = 5800;
|
|
17
17
|
const SCRCPY_SERVER_PORT = 5700;
|
|
18
|
+
const SCRCPY_ADB_CONNECT_TIMEOUT_MS = 10000;
|
|
19
|
+
const SCRCPY_PUSH_TIMEOUT_MS = 10000;
|
|
20
|
+
const SCRCPY_START_TIMEOUT_MS = 15000;
|
|
21
|
+
const SCRCPY_VIDEO_STREAM_TIMEOUT_MS = 15000;
|
|
22
|
+
const SCRCPY_PREVIEW_METADATA_TIMEOUT_MS = SCRCPY_ADB_CONNECT_TIMEOUT_MS + SCRCPY_PUSH_TIMEOUT_MS + SCRCPY_START_TIMEOUT_MS + SCRCPY_VIDEO_STREAM_TIMEOUT_MS + 5000;
|
|
18
23
|
const WEBDRIVER_ELEMENT_ID_KEY = 'element-6066-11e4-a52e-4f735466cecf';
|
|
19
24
|
const DEFAULT_WDA_PORT = 8100;
|
|
20
25
|
const DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT = 5000;
|
|
21
26
|
const DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT = 2000;
|
|
22
27
|
const DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY = 2;
|
|
23
|
-
export { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, DEFAULT_WDA_PORT, constants_NodeType as NodeType, PLAYGROUND_SERVER_PORT, PLAYWRIGHT_EXAMPLE_CODE, SCRCPY_SERVER_PORT, TEXT_MAX_SIZE, TEXT_SIZE_THRESHOLD, WEBDRIVER_ELEMENT_ID_KEY, YAML_EXAMPLE_CODE };
|
|
28
|
+
export { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, DEFAULT_WDA_PORT, constants_NodeType as NodeType, PLAYGROUND_SERVER_PORT, PLAYWRIGHT_EXAMPLE_CODE, SCRCPY_ADB_CONNECT_TIMEOUT_MS, SCRCPY_PREVIEW_METADATA_TIMEOUT_MS, SCRCPY_PUSH_TIMEOUT_MS, SCRCPY_SERVER_PORT, SCRCPY_START_TIMEOUT_MS, SCRCPY_VIDEO_STREAM_TIMEOUT_MS, TEXT_MAX_SIZE, TEXT_SIZE_THRESHOLD, WEBDRIVER_ELEMENT_ID_KEY, YAML_EXAMPLE_CODE };
|
|
@@ -24,14 +24,17 @@ class ModelConfigManager {
|
|
|
24
24
|
this.modelConfigMap = {
|
|
25
25
|
default: {
|
|
26
26
|
...defaultConfig,
|
|
27
|
+
intent: 'default',
|
|
27
28
|
createOpenAIClient: this.createOpenAIClientFn
|
|
28
29
|
},
|
|
29
30
|
insight: {
|
|
30
31
|
...insightConfig || defaultConfig,
|
|
32
|
+
intent: 'insight',
|
|
31
33
|
createOpenAIClient: this.createOpenAIClientFn
|
|
32
34
|
},
|
|
33
35
|
planning: {
|
|
34
36
|
...planningConfig || defaultConfig,
|
|
37
|
+
intent: 'planning',
|
|
35
38
|
createOpenAIClient: this.createOpenAIClientFn
|
|
36
39
|
}
|
|
37
40
|
};
|
|
@@ -4,6 +4,9 @@ import { getDebug } from "../logger.mjs";
|
|
|
4
4
|
import { assert } from "../utils.mjs";
|
|
5
5
|
import { maskConfig, parseJson } from "./helper.mjs";
|
|
6
6
|
import { initDebugConfig } from "./init-debug.mjs";
|
|
7
|
+
const MODEL_CONFIG_DOC_URL = 'https://midscenejs.com/model-common-config.html';
|
|
8
|
+
const getCurrentVersion = ()=>"8.0.3";
|
|
9
|
+
const getInvalidModelFamilyMessage = (modelFamily)=>`Invalid MIDSCENE_MODEL_FAMILY value: ${modelFamily}. Current version v${getCurrentVersion()} accepts the following model families: ${MODEL_FAMILY_VALUES.join(', ')}. You can also visit ${MODEL_CONFIG_DOC_URL} for the latest configuration information.`;
|
|
7
10
|
const KEYS_MAP = {
|
|
8
11
|
insight: INSIGHT_MODEL_CONFIG_KEYS,
|
|
9
12
|
planning: PLANNING_MODEL_CONFIG_KEYS,
|
|
@@ -14,7 +17,7 @@ const getUITarsModelVersion = (modelFamily)=>{
|
|
|
14
17
|
if ('vlm-ui-tars-doubao' === modelFamily || 'vlm-ui-tars-doubao-1.5' === modelFamily) return UITarsModelVersion.DOUBAO_1_5_20B;
|
|
15
18
|
};
|
|
16
19
|
const validateModelFamily = (modelFamily)=>{
|
|
17
|
-
if (modelFamily && !MODEL_FAMILY_VALUES.includes(modelFamily)) throw new Error(
|
|
20
|
+
if (modelFamily && !MODEL_FAMILY_VALUES.includes(modelFamily)) throw new Error(getInvalidModelFamilyMessage(modelFamily));
|
|
18
21
|
};
|
|
19
22
|
const legacyConfigToModelFamily = (provider)=>{
|
|
20
23
|
const isDoubao = provider[MIDSCENE_USE_DOUBAO_VISION];
|
|
@@ -90,6 +93,7 @@ const parseOpenaiSdkConfig = ({ keys, provider, useLegacyLogic = false })=>{
|
|
|
90
93
|
modelName: modelName,
|
|
91
94
|
modelDescription,
|
|
92
95
|
intent: '-',
|
|
96
|
+
slot: '-',
|
|
93
97
|
timeout: provider[keys.timeout] ? Number(provider[keys.timeout]) : void 0,
|
|
94
98
|
temperature,
|
|
95
99
|
retryCount: (()=>{
|
|
@@ -132,6 +136,7 @@ const decideModelConfigFromIntentConfig = (intent, configMap)=>{
|
|
|
132
136
|
useLegacyLogic: 'default' === intent
|
|
133
137
|
});
|
|
134
138
|
finalResult.intent = intent;
|
|
139
|
+
finalResult.slot = intent;
|
|
135
140
|
debugLog('decideModelConfig result by agent.modelConfig() with intent', intent, maskConfig({
|
|
136
141
|
...finalResult
|
|
137
142
|
}));
|
package/dist/es/env/types.mjs
CHANGED
|
@@ -35,6 +35,7 @@ const MIDSCENE_ADB_REMOTE_PORT = 'MIDSCENE_ADB_REMOTE_PORT';
|
|
|
35
35
|
const MIDSCENE_ANDROID_IME_STRATEGY = 'MIDSCENE_ANDROID_IME_STRATEGY';
|
|
36
36
|
const MIDSCENE_IOS_DEVICE_UDID = 'MIDSCENE_IOS_DEVICE_UDID';
|
|
37
37
|
const MIDSCENE_IOS_SIMULATOR_UDID = 'MIDSCENE_IOS_SIMULATOR_UDID';
|
|
38
|
+
const MIDSCENE_IOS_DEVICE_CLASS_OVERRIDE = 'MIDSCENE_IOS_DEVICE_CLASS_OVERRIDE';
|
|
38
39
|
const MIDSCENE_CACHE = 'MIDSCENE_CACHE';
|
|
39
40
|
const MIDSCENE_USE_VLM_UI_TARS = 'MIDSCENE_USE_VLM_UI_TARS';
|
|
40
41
|
const MIDSCENE_USE_QWEN_VL = 'MIDSCENE_USE_QWEN_VL';
|
|
@@ -209,4 +210,4 @@ var types_UITarsModelVersion = /*#__PURE__*/ function(UITarsModelVersion) {
|
|
|
209
210
|
UITarsModelVersion["DOUBAO_1_5_20B"] = "doubao-1.5-20B";
|
|
210
211
|
return UITarsModelVersion;
|
|
211
212
|
}({});
|
|
212
|
-
export { ALL_ENV_KEYS, BASIC_ENV_KEYS, BOOLEAN_ENV_KEYS, DOCKER_CONTAINER, GLOBAL_ENV_KEYS, MATCH_BY_POSITION, MIDSCENE_ADB_PATH, MIDSCENE_ADB_REMOTE_HOST, MIDSCENE_ADB_REMOTE_PORT, MIDSCENE_ANDROID_IME_STRATEGY, MIDSCENE_CACHE, MIDSCENE_CACHE_MAX_FILENAME_LENGTH, MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG, MIDSCENE_DEBUG_MODE, MIDSCENE_DEBUG_MODEL_PROFILE, MIDSCENE_DEBUG_MODEL_RESPONSE, MIDSCENE_INSIGHT_MODEL_API_KEY, MIDSCENE_INSIGHT_MODEL_BASE_URL, MIDSCENE_INSIGHT_MODEL_EXTRA_BODY_JSON, MIDSCENE_INSIGHT_MODEL_FAMILY, MIDSCENE_INSIGHT_MODEL_HTTP_PROXY, MIDSCENE_INSIGHT_MODEL_INIT_CONFIG_JSON, MIDSCENE_INSIGHT_MODEL_NAME, MIDSCENE_INSIGHT_MODEL_REASONING_BUDGET, MIDSCENE_INSIGHT_MODEL_REASONING_EFFORT, MIDSCENE_INSIGHT_MODEL_REASONING_ENABLED, MIDSCENE_INSIGHT_MODEL_RETRY_COUNT, MIDSCENE_INSIGHT_MODEL_RETRY_INTERVAL, MIDSCENE_INSIGHT_MODEL_SOCKS_PROXY, MIDSCENE_INSIGHT_MODEL_TEMPERATURE, MIDSCENE_INSIGHT_MODEL_TIMEOUT, MIDSCENE_IOS_DEVICE_UDID, MIDSCENE_IOS_SIMULATOR_UDID, MIDSCENE_LANGFUSE_DEBUG, MIDSCENE_LANGSMITH_DEBUG, MIDSCENE_MCP_ANDROID_MODE, MIDSCENE_MCP_CHROME_PATH, MIDSCENE_MCP_USE_PUPPETEER_MODE, MIDSCENE_MODEL_API_KEY, MIDSCENE_MODEL_BASE_URL, MIDSCENE_MODEL_EXTRA_BODY_JSON, MIDSCENE_MODEL_FAMILY, MIDSCENE_MODEL_HTTP_PROXY, MIDSCENE_MODEL_INIT_CONFIG_JSON, MIDSCENE_MODEL_MAX_TOKENS, MIDSCENE_MODEL_NAME, MIDSCENE_MODEL_REASONING_BUDGET, MIDSCENE_MODEL_REASONING_EFFORT, MIDSCENE_MODEL_REASONING_ENABLED, MIDSCENE_MODEL_RETRY_COUNT, MIDSCENE_MODEL_RETRY_INTERVAL, MIDSCENE_MODEL_SOCKS_PROXY, MIDSCENE_MODEL_TEMPERATURE, MIDSCENE_MODEL_TIMEOUT, MIDSCENE_OPENAI_HTTP_PROXY, MIDSCENE_OPENAI_INIT_CONFIG_JSON, MIDSCENE_OPENAI_SOCKS_PROXY, MIDSCENE_PLANNING_MODEL_API_KEY, MIDSCENE_PLANNING_MODEL_BASE_URL, MIDSCENE_PLANNING_MODEL_EXTRA_BODY_JSON, MIDSCENE_PLANNING_MODEL_FAMILY, MIDSCENE_PLANNING_MODEL_HTTP_PROXY, MIDSCENE_PLANNING_MODEL_INIT_CONFIG_JSON, MIDSCENE_PLANNING_MODEL_NAME, MIDSCENE_PLANNING_MODEL_REASONING_BUDGET, MIDSCENE_PLANNING_MODEL_REASONING_EFFORT, MIDSCENE_PLANNING_MODEL_REASONING_ENABLED, MIDSCENE_PLANNING_MODEL_RETRY_COUNT, MIDSCENE_PLANNING_MODEL_RETRY_INTERVAL, MIDSCENE_PLANNING_MODEL_SOCKS_PROXY, MIDSCENE_PLANNING_MODEL_TEMPERATURE, MIDSCENE_PLANNING_MODEL_TIMEOUT, MIDSCENE_PREFERRED_LANGUAGE, MIDSCENE_REPLANNING_CYCLE_LIMIT, MIDSCENE_REPORT_QUIET, MIDSCENE_REPORT_TAG_NAME, MIDSCENE_RUN_DIR, MIDSCENE_USE_DOUBAO_VISION, MIDSCENE_USE_GEMINI, MIDSCENE_USE_QWEN3_VL, MIDSCENE_USE_QWEN_VL, MIDSCENE_USE_VLM_UI_TARS, MIDSCENE_USE_VL_MODEL, MODEL_ENV_KEYS, MODEL_FAMILY_VALUES, NUMBER_ENV_KEYS, OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MAX_TOKENS, STRING_ENV_KEYS, types_UITarsModelVersion as UITarsModelVersion, UNUSED_ENV_KEYS };
|
|
213
|
+
export { ALL_ENV_KEYS, BASIC_ENV_KEYS, BOOLEAN_ENV_KEYS, DOCKER_CONTAINER, GLOBAL_ENV_KEYS, MATCH_BY_POSITION, MIDSCENE_ADB_PATH, MIDSCENE_ADB_REMOTE_HOST, MIDSCENE_ADB_REMOTE_PORT, MIDSCENE_ANDROID_IME_STRATEGY, MIDSCENE_CACHE, MIDSCENE_CACHE_MAX_FILENAME_LENGTH, MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG, MIDSCENE_DEBUG_MODE, MIDSCENE_DEBUG_MODEL_PROFILE, MIDSCENE_DEBUG_MODEL_RESPONSE, MIDSCENE_INSIGHT_MODEL_API_KEY, MIDSCENE_INSIGHT_MODEL_BASE_URL, MIDSCENE_INSIGHT_MODEL_EXTRA_BODY_JSON, MIDSCENE_INSIGHT_MODEL_FAMILY, MIDSCENE_INSIGHT_MODEL_HTTP_PROXY, MIDSCENE_INSIGHT_MODEL_INIT_CONFIG_JSON, MIDSCENE_INSIGHT_MODEL_NAME, MIDSCENE_INSIGHT_MODEL_REASONING_BUDGET, MIDSCENE_INSIGHT_MODEL_REASONING_EFFORT, MIDSCENE_INSIGHT_MODEL_REASONING_ENABLED, MIDSCENE_INSIGHT_MODEL_RETRY_COUNT, MIDSCENE_INSIGHT_MODEL_RETRY_INTERVAL, MIDSCENE_INSIGHT_MODEL_SOCKS_PROXY, MIDSCENE_INSIGHT_MODEL_TEMPERATURE, MIDSCENE_INSIGHT_MODEL_TIMEOUT, MIDSCENE_IOS_DEVICE_CLASS_OVERRIDE, MIDSCENE_IOS_DEVICE_UDID, MIDSCENE_IOS_SIMULATOR_UDID, MIDSCENE_LANGFUSE_DEBUG, MIDSCENE_LANGSMITH_DEBUG, MIDSCENE_MCP_ANDROID_MODE, MIDSCENE_MCP_CHROME_PATH, MIDSCENE_MCP_USE_PUPPETEER_MODE, MIDSCENE_MODEL_API_KEY, MIDSCENE_MODEL_BASE_URL, MIDSCENE_MODEL_EXTRA_BODY_JSON, MIDSCENE_MODEL_FAMILY, MIDSCENE_MODEL_HTTP_PROXY, MIDSCENE_MODEL_INIT_CONFIG_JSON, MIDSCENE_MODEL_MAX_TOKENS, MIDSCENE_MODEL_NAME, MIDSCENE_MODEL_REASONING_BUDGET, MIDSCENE_MODEL_REASONING_EFFORT, MIDSCENE_MODEL_REASONING_ENABLED, MIDSCENE_MODEL_RETRY_COUNT, MIDSCENE_MODEL_RETRY_INTERVAL, MIDSCENE_MODEL_SOCKS_PROXY, MIDSCENE_MODEL_TEMPERATURE, MIDSCENE_MODEL_TIMEOUT, MIDSCENE_OPENAI_HTTP_PROXY, MIDSCENE_OPENAI_INIT_CONFIG_JSON, MIDSCENE_OPENAI_SOCKS_PROXY, MIDSCENE_PLANNING_MODEL_API_KEY, MIDSCENE_PLANNING_MODEL_BASE_URL, MIDSCENE_PLANNING_MODEL_EXTRA_BODY_JSON, MIDSCENE_PLANNING_MODEL_FAMILY, MIDSCENE_PLANNING_MODEL_HTTP_PROXY, MIDSCENE_PLANNING_MODEL_INIT_CONFIG_JSON, MIDSCENE_PLANNING_MODEL_NAME, MIDSCENE_PLANNING_MODEL_REASONING_BUDGET, MIDSCENE_PLANNING_MODEL_REASONING_EFFORT, MIDSCENE_PLANNING_MODEL_REASONING_ENABLED, MIDSCENE_PLANNING_MODEL_RETRY_COUNT, MIDSCENE_PLANNING_MODEL_RETRY_INTERVAL, MIDSCENE_PLANNING_MODEL_SOCKS_PROXY, MIDSCENE_PLANNING_MODEL_TEMPERATURE, MIDSCENE_PLANNING_MODEL_TIMEOUT, MIDSCENE_PREFERRED_LANGUAGE, MIDSCENE_REPLANNING_CYCLE_LIMIT, MIDSCENE_REPORT_QUIET, MIDSCENE_REPORT_TAG_NAME, MIDSCENE_RUN_DIR, MIDSCENE_USE_DOUBAO_VISION, MIDSCENE_USE_GEMINI, MIDSCENE_USE_QWEN3_VL, MIDSCENE_USE_QWEN_VL, MIDSCENE_USE_VLM_UI_TARS, MIDSCENE_USE_VL_MODEL, MODEL_ENV_KEYS, MODEL_FAMILY_VALUES, NUMBER_ENV_KEYS, OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MAX_TOKENS, STRING_ENV_KEYS, types_UITarsModelVersion as UITarsModelVersion, UNUSED_ENV_KEYS };
|
package/dist/es/env/utils.mjs
CHANGED
|
@@ -5,14 +5,6 @@ const globalModelConfigManager = new ModelConfigManager();
|
|
|
5
5
|
const globalConfigManager = new GlobalConfigManager();
|
|
6
6
|
globalConfigManager.registerModelConfigManager(globalModelConfigManager);
|
|
7
7
|
globalModelConfigManager.registerGlobalConfigManager(globalConfigManager);
|
|
8
|
-
async function getCurrentTime(device, useDeviceTimestamp) {
|
|
9
|
-
if (useDeviceTimestamp && device?.getTimestamp) try {
|
|
10
|
-
return await device.getTimestamp();
|
|
11
|
-
} catch (error) {
|
|
12
|
-
console.warn(`Failed to get device time, falling back to system time: ${error}`);
|
|
13
|
-
}
|
|
14
|
-
return Date.now();
|
|
15
|
-
}
|
|
16
8
|
const getPreferredLanguage = ()=>{
|
|
17
9
|
const prefer = globalConfigManager.getEnvConfigValue(MIDSCENE_PREFERRED_LANGUAGE);
|
|
18
10
|
if (prefer) return prefer;
|
|
@@ -23,4 +15,4 @@ const getPreferredLanguage = ()=>{
|
|
|
23
15
|
const overrideAIConfig = (newConfig, extendMode = false)=>{
|
|
24
16
|
globalConfigManager.overrideAIConfig(newConfig, extendMode);
|
|
25
17
|
};
|
|
26
|
-
export {
|
|
18
|
+
export { getPreferredLanguage, globalConfigManager, globalModelConfigManager, overrideAIConfig };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { descriptionOfTree, traverseTree, treeToList, trimAttributes, truncateText } from "./tree.mjs";
|
|
2
2
|
import { extractTextWithPosition, extractTreeNode, extractTreeNodeAsString } from "./web-extractor.mjs";
|
|
3
3
|
import { getElementInfoByXpath, getElementXpath, getNodeInfoByXpath, getXpathsById, getXpathsByPoint } from "./locator.mjs";
|
|
4
|
-
import { generateElementByRect, isNotContainerElement } from "./dom-util.mjs";
|
|
5
|
-
export { descriptionOfTree, generateElementByRect, getElementInfoByXpath, getElementXpath, getNodeInfoByXpath, getXpathsById, getXpathsByPoint, isNotContainerElement, traverseTree, treeToList, trimAttributes, truncateText, extractTreeNode as webExtractNodeTree, extractTreeNodeAsString as webExtractNodeTreeAsString, extractTextWithPosition as webExtractTextWithPosition };
|
|
4
|
+
import { generateElementByPoint, generateElementByRect, isNotContainerElement } from "./dom-util.mjs";
|
|
5
|
+
export { descriptionOfTree, generateElementByPoint, generateElementByRect, getElementInfoByXpath, getElementXpath, getNodeInfoByXpath, getXpathsById, getXpathsByPoint, isNotContainerElement, traverseTree, treeToList, trimAttributes, truncateText, extractTreeNode as webExtractNodeTree, extractTreeNodeAsString as webExtractNodeTreeAsString, extractTextWithPosition as webExtractTextWithPosition };
|
package/dist/es/img/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { imageInfoOfBase64, isValidImageBuffer, isValidJPEGImageBuffer, isValidPNGImageBuffer } from "./info.mjs";
|
|
1
|
+
import { imageInfoOfBase64, isValidImageBuffer, isValidJPEGImageBuffer, isValidPNGImageBuffer, validateScreenshotBuffer } from "./info.mjs";
|
|
2
2
|
import { createImgBase64ByFormat, cropByRect, httpImg2Base64, localImg2Base64, paddingToMatchBlockByBase64, parseBase64, preProcessImageUrl, resizeAndConvertImgBuffer, resizeImgBase64, saveBase64Image, scaleImage, zoomForGPT4o } from "./transform.mjs";
|
|
3
3
|
import { annotateRects, compositeElementInfoImg, processImageElementInfo } from "./box-select.mjs";
|
|
4
|
-
export { annotateRects, compositeElementInfoImg, createImgBase64ByFormat, cropByRect, httpImg2Base64, imageInfoOfBase64, isValidImageBuffer, isValidJPEGImageBuffer, isValidPNGImageBuffer, localImg2Base64, paddingToMatchBlockByBase64, parseBase64, preProcessImageUrl, processImageElementInfo, resizeAndConvertImgBuffer, resizeImgBase64, saveBase64Image, scaleImage, zoomForGPT4o };
|
|
4
|
+
export { annotateRects, compositeElementInfoImg, createImgBase64ByFormat, cropByRect, httpImg2Base64, imageInfoOfBase64, isValidImageBuffer, isValidJPEGImageBuffer, isValidPNGImageBuffer, localImg2Base64, paddingToMatchBlockByBase64, parseBase64, preProcessImageUrl, processImageElementInfo, resizeAndConvertImgBuffer, resizeImgBase64, saveBase64Image, scaleImage, validateScreenshotBuffer, zoomForGPT4o };
|
package/dist/es/img/info.mjs
CHANGED
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
import node_assert from "node:assert";
|
|
2
2
|
import get_photon from "./get-photon.mjs";
|
|
3
3
|
async function imageInfoOfBase64(imageBase64) {
|
|
4
|
-
|
|
4
|
+
const { PhotonImage } = await get_photon();
|
|
5
5
|
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, '');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
node_assert(width && height, 'Invalid image: cannot get width or height');
|
|
17
|
-
return {
|
|
18
|
-
width,
|
|
19
|
-
height
|
|
20
|
-
};
|
|
21
|
-
} catch (error) {
|
|
22
|
-
if (error instanceof Error && error.message.includes('unreachable')) throw new Error(`Failed to decode image: invalid or corrupted image data. Original error: ${error.message}`);
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
6
|
+
const result = PhotonImage.new_from_base64(base64Data);
|
|
7
|
+
const image = result instanceof Promise ? await result : result;
|
|
8
|
+
const width = image.get_width();
|
|
9
|
+
const height = image.get_height();
|
|
10
|
+
image.free();
|
|
11
|
+
node_assert(width && height, 'Invalid image: cannot get width or height');
|
|
12
|
+
return {
|
|
13
|
+
width,
|
|
14
|
+
height
|
|
15
|
+
};
|
|
25
16
|
}
|
|
26
17
|
function isValidPNGImageBuffer(buffer) {
|
|
27
18
|
if (!buffer || buffer.length < 8) return false;
|
|
@@ -35,4 +26,10 @@ function isValidJPEGImageBuffer(buffer) {
|
|
|
35
26
|
function isValidImageBuffer(buffer) {
|
|
36
27
|
return isValidPNGImageBuffer(buffer) || isValidJPEGImageBuffer(buffer);
|
|
37
28
|
}
|
|
38
|
-
|
|
29
|
+
function validateScreenshotBuffer(screenshotBuffer, { label, minBufferSize = 0 }) {
|
|
30
|
+
const bufferSize = screenshotBuffer?.length ?? 0;
|
|
31
|
+
if (!screenshotBuffer || 0 === bufferSize) throw new Error(`${label} validation failed: buffer size ${bufferSize} bytes`);
|
|
32
|
+
if (!isValidImageBuffer(screenshotBuffer)) throw new Error(`${label} buffer has invalid image format`);
|
|
33
|
+
if (minBufferSize > 0 && bufferSize < minBufferSize) throw new Error(`${label} validation failed: buffer size ${bufferSize} bytes (minimum: ${minBufferSize})`);
|
|
34
|
+
}
|
|
35
|
+
export { imageInfoOfBase64, isValidImageBuffer, isValidJPEGImageBuffer, isValidPNGImageBuffer, validateScreenshotBuffer };
|
|
@@ -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,9 +1,10 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { setIsMcp } from "@aiscene/shared/utils";
|
|
2
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
5
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
6
|
import express from "express";
|
|
6
|
-
import {
|
|
7
|
+
import { getErrorMessage } from "./error-formatter.mjs";
|
|
7
8
|
function _define_property(obj, key, value) {
|
|
8
9
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
9
10
|
value: value,
|
|
@@ -45,7 +46,7 @@ class BaseMCPServer {
|
|
|
45
46
|
try {
|
|
46
47
|
await this.toolsManager.initTools();
|
|
47
48
|
} catch (error) {
|
|
48
|
-
const message =
|
|
49
|
+
const message = getErrorMessage(error);
|
|
49
50
|
console.error(`Failed to initialize tools: ${message}`);
|
|
50
51
|
console.error('Tools will be initialized on first use');
|
|
51
52
|
}
|
|
@@ -71,7 +72,7 @@ class BaseMCPServer {
|
|
|
71
72
|
try {
|
|
72
73
|
await this.mcpServer.connect(transport);
|
|
73
74
|
} catch (error) {
|
|
74
|
-
const message =
|
|
75
|
+
const message = getErrorMessage(error);
|
|
75
76
|
console.error(`Failed to connect MCP stdio transport: ${message}`);
|
|
76
77
|
throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
|
|
77
78
|
}
|
|
@@ -142,7 +143,7 @@ class BaseMCPServer {
|
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
} catch (error) {
|
|
145
|
-
const message =
|
|
146
|
+
const message = getErrorMessage(error);
|
|
146
147
|
const duration = Date.now() - startTime;
|
|
147
148
|
console.error(`[${new Date().toISOString()}] [${requestId}] MCP request error after ${duration}ms: ${message}`);
|
|
148
149
|
if (!res.headersSent) res.status(500).json({
|
|
@@ -170,7 +171,7 @@ class BaseMCPServer {
|
|
|
170
171
|
for (const session of sessions.values())try {
|
|
171
172
|
await session.transport.close();
|
|
172
173
|
} catch (error) {
|
|
173
|
-
const message =
|
|
174
|
+
const message = getErrorMessage(error);
|
|
174
175
|
console.error(`Failed to close session ${session.transport.sessionId}: ${message}`);
|
|
175
176
|
}
|
|
176
177
|
sessions.clear();
|
|
@@ -205,7 +206,7 @@ class BaseMCPServer {
|
|
|
205
206
|
try {
|
|
206
207
|
await this.mcpServer.connect(transport);
|
|
207
208
|
} catch (error) {
|
|
208
|
-
const message =
|
|
209
|
+
const message = getErrorMessage(error);
|
|
209
210
|
console.error(`[${new Date().toISOString()}] Failed to connect MCP transport: ${message}`);
|
|
210
211
|
if (transport.sessionId) sessions.delete(transport.sessionId);
|
|
211
212
|
throw new Error(`Failed to initialize MCP session: ${message}`);
|
|
@@ -224,7 +225,7 @@ class BaseMCPServer {
|
|
|
224
225
|
sessions.delete(sid);
|
|
225
226
|
console.log(`[${new Date().toISOString()}] Session ${sid} cleaned up due to inactivity (remaining: ${sessions.size})`);
|
|
226
227
|
} catch (error) {
|
|
227
|
-
const message =
|
|
228
|
+
const message = getErrorMessage(error);
|
|
228
229
|
console.error(`[${new Date().toISOString()}] Failed to close session ${sid} during cleanup: ${message}`);
|
|
229
230
|
sessions.delete(sid);
|
|
230
231
|
}
|
|
@@ -237,7 +238,7 @@ class BaseMCPServer {
|
|
|
237
238
|
for (const session of sessions.values())try {
|
|
238
239
|
session.transport.close();
|
|
239
240
|
} catch (error) {
|
|
240
|
-
const message =
|
|
241
|
+
const message = getErrorMessage(error);
|
|
241
242
|
console.error(`Error closing session during shutdown: ${message}`);
|
|
242
243
|
}
|
|
243
244
|
sessions.clear();
|
|
@@ -250,7 +251,7 @@ class BaseMCPServer {
|
|
|
250
251
|
this.performCleanup().finally(()=>process.exit(1));
|
|
251
252
|
}, 5000);
|
|
252
253
|
} catch (error) {
|
|
253
|
-
const message =
|
|
254
|
+
const message = getErrorMessage(error);
|
|
254
255
|
console.error(`Error closing HTTP server: ${message}`);
|
|
255
256
|
this.performCleanup().finally(()=>process.exit(1));
|
|
256
257
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { parseBase64 } from "
|
|
2
|
-
import { getDebug } from "
|
|
1
|
+
import { parseBase64 } from "@aiscene/shared/img";
|
|
2
|
+
import { getDebug } from "@aiscene/shared/logger";
|
|
3
|
+
import { camelToKebab, getKeyAliases } from "../key-alias-utils.mjs";
|
|
4
|
+
import { generateCliReportSession, readCliReportSession, writeCliReportSession } from "./cli-report-session.mjs";
|
|
5
|
+
import { createNamespacedInitArgSchema, extractNamespacedArgs, sanitizeNamespacedArgs } from "./init-arg-utils.mjs";
|
|
3
6
|
import { generateCommonTools, generateToolsFromActionSpace } from "./tool-generator.mjs";
|
|
4
7
|
function _define_property(obj, key, value) {
|
|
5
8
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -13,9 +16,74 @@ function _define_property(obj, key, value) {
|
|
|
13
16
|
}
|
|
14
17
|
const debug = getDebug('mcp:base-tools');
|
|
15
18
|
class BaseMidsceneTools {
|
|
19
|
+
getInitArgKeys() {
|
|
20
|
+
return this.initArgSpec ? Object.keys(this.initArgSpec.shape) : [];
|
|
21
|
+
}
|
|
22
|
+
extractAgentInitParam(args) {
|
|
23
|
+
if (!this.initArgSpec) return;
|
|
24
|
+
const extracted = extractNamespacedArgs(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
25
|
+
if (this.initArgSpec.adapt) return this.initArgSpec.adapt(extracted);
|
|
26
|
+
return extracted;
|
|
27
|
+
}
|
|
28
|
+
sanitizeToolArgs(args) {
|
|
29
|
+
if (!this.initArgSpec) return args;
|
|
30
|
+
return sanitizeNamespacedArgs(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
31
|
+
}
|
|
32
|
+
getAgentInitArgSchema() {
|
|
33
|
+
if (!this.initArgSpec) return {};
|
|
34
|
+
return createNamespacedInitArgSchema(this.initArgSpec.namespace, this.initArgSpec.shape);
|
|
35
|
+
}
|
|
36
|
+
getAgentInitArgCliMetadata() {
|
|
37
|
+
if (!this.initArgSpec?.cli) return;
|
|
38
|
+
const options = Object.fromEntries(this.getInitArgKeys().map((key)=>{
|
|
39
|
+
const canonicalKey = `${this.initArgSpec.namespace}.${key}`;
|
|
40
|
+
const preferredName = this.initArgSpec.cli?.preferredNames?.[key] ?? (this.initArgSpec.cli?.preferBareKeys ? camelToKebab(key) : canonicalKey);
|
|
41
|
+
const acceptedNames = new Set([
|
|
42
|
+
preferredName,
|
|
43
|
+
...this.initArgSpec.cli?.preferBareKeys ? getKeyAliases(key) : getKeyAliases(canonicalKey)
|
|
44
|
+
]);
|
|
45
|
+
acceptedNames.delete(preferredName);
|
|
46
|
+
return [
|
|
47
|
+
canonicalKey,
|
|
48
|
+
{
|
|
49
|
+
preferredName,
|
|
50
|
+
aliases: [
|
|
51
|
+
...acceptedNames
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
];
|
|
55
|
+
}));
|
|
56
|
+
return {
|
|
57
|
+
options
|
|
58
|
+
};
|
|
59
|
+
}
|
|
16
60
|
preparePlatformTools() {
|
|
17
61
|
return [];
|
|
18
62
|
}
|
|
63
|
+
getCliReportSessionName() {}
|
|
64
|
+
createNewCliReportSession(targetIdentity) {
|
|
65
|
+
const sessionName = this.getCliReportSessionName();
|
|
66
|
+
if (!sessionName) return;
|
|
67
|
+
return generateCliReportSession(sessionName, targetIdentity);
|
|
68
|
+
}
|
|
69
|
+
commitCliReportSession(session) {
|
|
70
|
+
if (session) writeCliReportSession(session);
|
|
71
|
+
}
|
|
72
|
+
readCliReportFileName() {
|
|
73
|
+
const sessionName = this.getCliReportSessionName();
|
|
74
|
+
if (!sessionName) return;
|
|
75
|
+
return readCliReportSession(sessionName)?.reportFileName;
|
|
76
|
+
}
|
|
77
|
+
readCliReportAgentOptions() {
|
|
78
|
+
const reportFileName = this.readCliReportFileName();
|
|
79
|
+
if (!reportFileName) return;
|
|
80
|
+
return {
|
|
81
|
+
reportFileName,
|
|
82
|
+
reportAttributes: {
|
|
83
|
+
'data-group-id': reportFileName
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
19
87
|
async initTools() {
|
|
20
88
|
this.toolDefinitions = [];
|
|
21
89
|
const platformTools = this.preparePlatformTools();
|
|
@@ -30,8 +98,8 @@ class BaseMidsceneTools {
|
|
|
30
98
|
await tempDevice.destroy?.();
|
|
31
99
|
debug('Action space from temporary device:', actionSpace.map((a)=>a.name).join(', '));
|
|
32
100
|
}
|
|
33
|
-
const actionTools = generateToolsFromActionSpace(actionSpace, ()=>this.ensureAgent());
|
|
34
|
-
const commonTools = generateCommonTools(()=>this.ensureAgent());
|
|
101
|
+
const actionTools = generateToolsFromActionSpace(actionSpace, (args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), (args = {})=>this.sanitizeToolArgs(args), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata());
|
|
102
|
+
const commonTools = generateCommonTools((args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata());
|
|
35
103
|
this.toolDefinitions.push(...actionTools, ...commonTools);
|
|
36
104
|
debug('Total tools prepared:', this.toolDefinitions.length);
|
|
37
105
|
}
|