@ui-tars-test/cli 0.3.2 → 0.3.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/cli/commands.js +1 -1
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/commands.mjs +1 -1
- package/dist/cli/commands.mjs.map +1 -1
- package/dist/cli/start.js +371 -77
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/start.mjs +369 -77
- package/dist/cli/start.mjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/start.d.ts +1 -0
- package/dist/src/cli/start.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/commands.js
CHANGED
|
@@ -35,7 +35,7 @@ const external_package_json_namespaceObject = require("../../package.json");
|
|
|
35
35
|
const external_start_js_namespaceObject = require("./start.js");
|
|
36
36
|
const run = ()=>{
|
|
37
37
|
external_commander_namespaceObject.program.name('gui-agent').description('CLI for GUI Agent automation').usage('<command> [options]').version(`GUI Agent CLI v${external_package_json_namespaceObject.version} \u{1F680}`, '-v, --version', 'Display the version number');
|
|
38
|
-
external_commander_namespaceObject.program.command('run').description('Run GUI Agent automation').option('-p, --presets <url>', 'Load model configuration from preset URL').option('-t, --target <target>', 'Target automation type (computer, browser, android)').option('-q, --query <query>', 'Instruction to execute (optional, will prompt if not provided)').option('-c, --config <path>', 'Path to configuration file').option('-o, --output <dir>', 'Directory to store execution results').option('--tasks <file>', "Path to tasks JSON file containing a list of {taskId, query}. Use 'demo' to run built-in sample tasks").action(async (options)=>{
|
|
38
|
+
external_commander_namespaceObject.program.command('run').description('Run GUI Agent automation').option('-p, --presets <url>', 'Load model configuration from preset URL').option('-t, --target <target>', 'Target automation type (computer, browser, android)').option('-q, --query <query>', 'Instruction to execute (optional, will prompt if not provided)').option('-c, --config <path>', 'Path to configuration file').option('-o, --output <dir>', 'Directory to store execution results').option('-f, --tasks <file>', "Path to tasks JSON file containing a list of {taskId, query}. Use 'demo' to run built-in sample tasks").option('-l, --max-loop-count <number>', 'Maximum number of loops to run', '1000').action(async (options)=>{
|
|
39
39
|
try {
|
|
40
40
|
await (0, external_start_js_namespaceObject.start)(options);
|
|
41
41
|
} catch (err) {
|
package/dist/cli/commands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli/commands.js","sources":["webpack://@
|
|
1
|
+
{"version":3,"file":"cli/commands.js","sources":["webpack://@ui-tars-test/cli/webpack/runtime/define_property_getters","webpack://@ui-tars-test/cli/webpack/runtime/has_own_property","webpack://@ui-tars-test/cli/webpack/runtime/make_namespace_object","webpack://@ui-tars-test/cli/./src/cli/commands.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { program } from 'commander';\n\nimport { version } from '../../package.json';\nimport { CliOptions, start, resetConfig } from './start';\n\nexport const run = () => {\n program\n .name('gui-agent')\n .description('CLI for GUI Agent automation')\n .usage('<command> [options]')\n .version(`GUI Agent CLI v${version} 🚀`, '-v, --version', 'Display the version number');\n\n program\n .command('run')\n .description('Run GUI Agent automation')\n .option('-p, --presets <url>', 'Load model configuration from preset URL')\n .option('-t, --target <target>', 'Target automation type (computer, browser, android)')\n .option('-q, --query <query>', 'Instruction to execute (optional, will prompt if not provided)')\n .option('-c, --config <path>', 'Path to configuration file')\n .option('-o, --output <dir>', 'Directory to store execution results')\n .option(\n '-f, --tasks <file>',\n \"Path to tasks JSON file containing a list of {taskId, query}. Use 'demo' to run built-in sample tasks\",\n )\n .option('-l, --max-loop-count <number>', 'Maximum number of loops to run', '1000')\n .action(async (options: CliOptions) => {\n try {\n await start(options);\n } catch (err) {\n console.error('Failed to run');\n console.error(err);\n process.exit(1);\n }\n });\n\n program\n .command('reset')\n .description('Reset stored configuration (API keys, model settings, etc.)')\n .option(\n '-c, --config <path>',\n 'Reset specific configuration file (default: ~/.gui-agent-cli.json)',\n )\n .action(async (options) => {\n try {\n await resetConfig(options.config);\n } catch (err) {\n console.error('Failed to reset configuration');\n console.error(err);\n process.exit(1);\n }\n });\n\n // Show help if no command provided\n if (process.argv.length <= 2) {\n program.outputHelp();\n console.log('\\nExamples:');\n console.log(' gui-agent run # Run with interactive prompts');\n console.log(' gui-agent run -t android # Run with Android automation');\n console.log(' gui-agent run -q \"open calculator\" # Run with specific instruction');\n console.log(' gui-agent reset # Reset all configuration');\n console.log(' gui-agent reset -c custom.json # Reset specific config file');\n }\n\n program.parse();\n};\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","run","program","version","options","start","err","console","process","resetConfig"],"mappings":";;;;;;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;ACGO,MAAMI,MAAM;IACjBC,mCAAAA,OAAAA,CAAAA,IACO,CAAC,aACL,WAAW,CAAC,gCACZ,KAAK,CAAC,uBACN,OAAO,CAAC,CAAC,eAAe,EAAEC,sCAAAA,OAAOA,CAAC,UAAG,CAAC,EAAE,iBAAiB;IAE5DD,mCAAAA,OAAAA,CAAAA,OACU,CAAC,OACR,WAAW,CAAC,4BACZ,MAAM,CAAC,uBAAuB,4CAC9B,MAAM,CAAC,yBAAyB,uDAChC,MAAM,CAAC,uBAAuB,kEAC9B,MAAM,CAAC,uBAAuB,8BAC9B,MAAM,CAAC,sBAAsB,wCAC7B,MAAM,CACL,sBACA,yGAED,MAAM,CAAC,iCAAiC,kCAAkC,QAC1E,MAAM,CAAC,OAAOE;QACb,IAAI;YACF,MAAMC,AAAAA,IAAAA,kCAAAA,KAAAA,AAAAA,EAAMD;QACd,EAAE,OAAOE,KAAK;YACZC,QAAQ,KAAK,CAAC;YACdA,QAAQ,KAAK,CAACD;YACdE,QAAQ,IAAI,CAAC;QACf;IACF;IAEFN,mCAAAA,OAAAA,CAAAA,OACU,CAAC,SACR,WAAW,CAAC,+DACZ,MAAM,CACL,uBACA,sEAED,MAAM,CAAC,OAAOE;QACb,IAAI;YACF,MAAMK,AAAAA,IAAAA,kCAAAA,WAAAA,AAAAA,EAAYL,QAAQ,MAAM;QAClC,EAAE,OAAOE,KAAK;YACZC,QAAQ,KAAK,CAAC;YACdA,QAAQ,KAAK,CAACD;YACdE,QAAQ,IAAI,CAAC;QACf;IACF;IAGF,IAAIA,QAAQ,IAAI,CAAC,MAAM,IAAI,GAAG;QAC5BN,mCAAAA,OAAAA,CAAAA,UAAkB;QAClBK,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;IACd;IAEAL,mCAAAA,OAAAA,CAAAA,KAAa;AACf"}
|
package/dist/cli/commands.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { version } from "../../package.json";
|
|
|
7
7
|
import { resetConfig, start } from "./start.mjs";
|
|
8
8
|
const run = ()=>{
|
|
9
9
|
program.name('gui-agent').description('CLI for GUI Agent automation').usage('<command> [options]').version(`GUI Agent CLI v${version} \u{1F680}`, '-v, --version', 'Display the version number');
|
|
10
|
-
program.command('run').description('Run GUI Agent automation').option('-p, --presets <url>', 'Load model configuration from preset URL').option('-t, --target <target>', 'Target automation type (computer, browser, android)').option('-q, --query <query>', 'Instruction to execute (optional, will prompt if not provided)').option('-c, --config <path>', 'Path to configuration file').option('-o, --output <dir>', 'Directory to store execution results').option('--tasks <file>', "Path to tasks JSON file containing a list of {taskId, query}. Use 'demo' to run built-in sample tasks").action(async (options)=>{
|
|
10
|
+
program.command('run').description('Run GUI Agent automation').option('-p, --presets <url>', 'Load model configuration from preset URL').option('-t, --target <target>', 'Target automation type (computer, browser, android)').option('-q, --query <query>', 'Instruction to execute (optional, will prompt if not provided)').option('-c, --config <path>', 'Path to configuration file').option('-o, --output <dir>', 'Directory to store execution results').option('-f, --tasks <file>', "Path to tasks JSON file containing a list of {taskId, query}. Use 'demo' to run built-in sample tasks").option('-l, --max-loop-count <number>', 'Maximum number of loops to run', '1000').action(async (options)=>{
|
|
11
11
|
try {
|
|
12
12
|
await start(options);
|
|
13
13
|
} catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli/commands.mjs","sources":["webpack://@
|
|
1
|
+
{"version":3,"file":"cli/commands.mjs","sources":["webpack://@ui-tars-test/cli/./src/cli/commands.ts"],"sourcesContent":["/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { program } from 'commander';\n\nimport { version } from '../../package.json';\nimport { CliOptions, start, resetConfig } from './start';\n\nexport const run = () => {\n program\n .name('gui-agent')\n .description('CLI for GUI Agent automation')\n .usage('<command> [options]')\n .version(`GUI Agent CLI v${version} 🚀`, '-v, --version', 'Display the version number');\n\n program\n .command('run')\n .description('Run GUI Agent automation')\n .option('-p, --presets <url>', 'Load model configuration from preset URL')\n .option('-t, --target <target>', 'Target automation type (computer, browser, android)')\n .option('-q, --query <query>', 'Instruction to execute (optional, will prompt if not provided)')\n .option('-c, --config <path>', 'Path to configuration file')\n .option('-o, --output <dir>', 'Directory to store execution results')\n .option(\n '-f, --tasks <file>',\n \"Path to tasks JSON file containing a list of {taskId, query}. Use 'demo' to run built-in sample tasks\",\n )\n .option('-l, --max-loop-count <number>', 'Maximum number of loops to run', '1000')\n .action(async (options: CliOptions) => {\n try {\n await start(options);\n } catch (err) {\n console.error('Failed to run');\n console.error(err);\n process.exit(1);\n }\n });\n\n program\n .command('reset')\n .description('Reset stored configuration (API keys, model settings, etc.)')\n .option(\n '-c, --config <path>',\n 'Reset specific configuration file (default: ~/.gui-agent-cli.json)',\n )\n .action(async (options) => {\n try {\n await resetConfig(options.config);\n } catch (err) {\n console.error('Failed to reset configuration');\n console.error(err);\n process.exit(1);\n }\n });\n\n // Show help if no command provided\n if (process.argv.length <= 2) {\n program.outputHelp();\n console.log('\\nExamples:');\n console.log(' gui-agent run # Run with interactive prompts');\n console.log(' gui-agent run -t android # Run with Android automation');\n console.log(' gui-agent run -q \"open calculator\" # Run with specific instruction');\n console.log(' gui-agent reset # Reset all configuration');\n console.log(' gui-agent reset -c custom.json # Reset specific config file');\n }\n\n program.parse();\n};\n"],"names":["run","program","version","options","start","err","console","process","resetConfig"],"mappings":";;;;;;;AASO,MAAMA,MAAM;IACjBC,QAAAA,IACO,CAAC,aACL,WAAW,CAAC,gCACZ,KAAK,CAAC,uBACN,OAAO,CAAC,CAAC,eAAe,EAAEC,QAAQ,UAAG,CAAC,EAAE,iBAAiB;IAE5DD,QAAAA,OACU,CAAC,OACR,WAAW,CAAC,4BACZ,MAAM,CAAC,uBAAuB,4CAC9B,MAAM,CAAC,yBAAyB,uDAChC,MAAM,CAAC,uBAAuB,kEAC9B,MAAM,CAAC,uBAAuB,8BAC9B,MAAM,CAAC,sBAAsB,wCAC7B,MAAM,CACL,sBACA,yGAED,MAAM,CAAC,iCAAiC,kCAAkC,QAC1E,MAAM,CAAC,OAAOE;QACb,IAAI;YACF,MAAMC,MAAMD;QACd,EAAE,OAAOE,KAAK;YACZC,QAAQ,KAAK,CAAC;YACdA,QAAQ,KAAK,CAACD;YACdE,QAAQ,IAAI,CAAC;QACf;IACF;IAEFN,QAAAA,OACU,CAAC,SACR,WAAW,CAAC,+DACZ,MAAM,CACL,uBACA,sEAED,MAAM,CAAC,OAAOE;QACb,IAAI;YACF,MAAMK,YAAYL,QAAQ,MAAM;QAClC,EAAE,OAAOE,KAAK;YACZC,QAAQ,KAAK,CAAC;YACdA,QAAQ,KAAK,CAACD;YACdE,QAAQ,IAAI,CAAC;QACf;IACF;IAGF,IAAIA,QAAQ,IAAI,CAAC,MAAM,IAAI,GAAG;QAC5BN,QAAQ,UAAU;QAClBK,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;QACZA,QAAQ,GAAG,CAAC;IACd;IAEAL,QAAQ,KAAK;AACf"}
|
package/dist/cli/start.js
CHANGED
|
@@ -46,16 +46,76 @@ const external_node_path_namespaceObject = require("node:path");
|
|
|
46
46
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
47
47
|
const external_node_os_namespaceObject = require("node:os");
|
|
48
48
|
var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
|
|
49
|
+
const external_fluent_ffmpeg_namespaceObject = require("fluent-ffmpeg");
|
|
50
|
+
var external_fluent_ffmpeg_default = /*#__PURE__*/ __webpack_require__.n(external_fluent_ffmpeg_namespaceObject);
|
|
51
|
+
const external_ffmpeg_static_namespaceObject = require("ffmpeg-static");
|
|
52
|
+
var external_ffmpeg_static_default = /*#__PURE__*/ __webpack_require__.n(external_ffmpeg_static_namespaceObject);
|
|
49
53
|
const external_node_fetch_namespaceObject = require("node-fetch");
|
|
50
54
|
var external_node_fetch_default = /*#__PURE__*/ __webpack_require__.n(external_node_fetch_namespaceObject);
|
|
51
|
-
const agent_sdk_namespaceObject = require("@
|
|
55
|
+
const agent_sdk_namespaceObject = require("@ui-tars-test/agent-sdk");
|
|
52
56
|
const prompts_namespaceObject = require("@clack/prompts");
|
|
53
57
|
const external_js_yaml_namespaceObject = require("js-yaml");
|
|
54
58
|
var external_js_yaml_default = /*#__PURE__*/ __webpack_require__.n(external_js_yaml_namespaceObject);
|
|
55
|
-
const operator_nutjs_namespaceObject = require("@
|
|
56
|
-
const operator_adb_namespaceObject = require("@
|
|
57
|
-
const operator_browser_namespaceObject = require("@
|
|
59
|
+
const operator_nutjs_namespaceObject = require("@ui-tars-test/operator-nutjs");
|
|
60
|
+
const operator_adb_namespaceObject = require("@ui-tars-test/operator-adb");
|
|
61
|
+
const operator_browser_namespaceObject = require("@ui-tars-test/operator-browser");
|
|
62
|
+
const saveConversationLog = (events, targetOutputDir, sessionId)=>{
|
|
63
|
+
const logPath = external_node_path_default().join(targetOutputDir, `${sessionId}.md`);
|
|
64
|
+
let content = `# Conversation Log - ${sessionId}\n\n`;
|
|
65
|
+
events.forEach((e)=>{
|
|
66
|
+
const time = new Date(e.timestamp || Date.now()).toISOString();
|
|
67
|
+
content += `## [${time}] ${e.type}\n`;
|
|
68
|
+
if (e.content) if (Array.isArray(e.content)) e.content.forEach((part)=>{
|
|
69
|
+
if ('text' === part.type) content += `${part.text}\n`;
|
|
70
|
+
if ('image_url' === part.type) content += `[Image Content]\n`;
|
|
71
|
+
});
|
|
72
|
+
else if ('string' == typeof e.content) content += `${e.content}\n`;
|
|
73
|
+
else content += `\`\`\`json\n${JSON.stringify(e.content, null, 2)}\n\`\`\`\n`;
|
|
74
|
+
if ('tool_call' === e.type) {
|
|
75
|
+
if (e.name) content += `> Tool Call: ${e.name}\n`;
|
|
76
|
+
if (e.arguments) content += `> Arguments: ${JSON.stringify(e.arguments, null, 2)}\n`;
|
|
77
|
+
const toolCall = e.toolCall;
|
|
78
|
+
if (toolCall) {
|
|
79
|
+
if (toolCall.name) content += `> Tool Call: ${toolCall.name}\n`;
|
|
80
|
+
if (toolCall.arguments) content += `> Arguments: ${JSON.stringify(toolCall.arguments, null, 2)}\n`;
|
|
81
|
+
}
|
|
82
|
+
} else if ('assistant_message' === e.type) {
|
|
83
|
+
if (e.content) content += `${e.content}\n`;
|
|
84
|
+
if (e.rawContent) content += `\n> Raw Content (Debug): ${JSON.stringify(e.rawContent)}\n`;
|
|
85
|
+
if (e.toolCalls) content += `> Tool Calls: ${JSON.stringify(e.toolCalls, null, 2)}\n`;
|
|
86
|
+
const message = e.message;
|
|
87
|
+
if (message) {
|
|
88
|
+
if (message.content) content += `${message.content}\n`;
|
|
89
|
+
if (message.rawContent) content += `\n> Raw Content (Debug): ${JSON.stringify(message.rawContent)}\n`;
|
|
90
|
+
if (message.tool_calls) content += `> Tool Calls: ${JSON.stringify(message.tool_calls, null, 2)}\n`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (e.metadata) if ('screenshot' === e.metadata.type) content += `> Action: Screenshot captured\n`;
|
|
94
|
+
else content += `> Metadata: ${JSON.stringify(e.metadata)}\n`;
|
|
95
|
+
if (e.input) content += `> Input: ${JSON.stringify(e.input, null, 2)}\n`;
|
|
96
|
+
if (e.output) content += `> Output: ${JSON.stringify(e.output, null, 2)}\n`;
|
|
97
|
+
content += '\n';
|
|
98
|
+
});
|
|
99
|
+
try {
|
|
100
|
+
external_node_fs_default().writeFileSync(logPath, content);
|
|
101
|
+
console.log(`[CLI] Conversation log saved: ${logPath}`);
|
|
102
|
+
return logPath;
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.warn(`[CLI] Failed to save conversation log: ${err}`);
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
58
108
|
const start = async (options)=>{
|
|
109
|
+
if (external_ffmpeg_static_default()) {
|
|
110
|
+
let finalFfmpegPath = external_ffmpeg_static_default();
|
|
111
|
+
const bundledFfmpegPath = external_node_path_default().join(__dirname, 'ffmpeg');
|
|
112
|
+
if (external_node_fs_default().existsSync(bundledFfmpegPath)) {
|
|
113
|
+
finalFfmpegPath = bundledFfmpegPath;
|
|
114
|
+
console.log(`[CLI] Using bundled ffmpeg: ${finalFfmpegPath}`);
|
|
115
|
+
} else console.log(`[CLI] Using default ffmpeg-static path: ${finalFfmpegPath}`);
|
|
116
|
+
if ('darwin' === external_node_os_default().platform() && 'arm64' === external_node_os_default().arch()) console.log(`[CLI] Setting ffmpeg path: ${finalFfmpegPath}`);
|
|
117
|
+
external_fluent_ffmpeg_default().setFfmpegPath(finalFfmpegPath);
|
|
118
|
+
} else console.warn('[CLI] ffmpeg-static not found. Video generation might fail if ffmpeg is not in PATH.');
|
|
59
119
|
const CONFIG_PATH = options.config || external_node_path_default().join(external_node_os_default().homedir(), '.gui-agent-cli.json');
|
|
60
120
|
let config = {
|
|
61
121
|
baseURL: '',
|
|
@@ -63,7 +123,7 @@ const start = async (options)=>{
|
|
|
63
123
|
model: '',
|
|
64
124
|
provider: 'openai',
|
|
65
125
|
useResponsesApi: false,
|
|
66
|
-
maxLoopCount: 1000
|
|
126
|
+
maxLoopCount: options.maxLoopCount ? Number(options.maxLoopCount) : 1000
|
|
67
127
|
};
|
|
68
128
|
if (options.presets) {
|
|
69
129
|
const response = await external_node_fetch_default()(options.presets);
|
|
@@ -315,111 +375,345 @@ const start = async (options)=>{
|
|
|
315
375
|
external_node_fs_default().mkdirSync(targetOutputDir, {
|
|
316
376
|
recursive: true
|
|
317
377
|
});
|
|
318
|
-
for (const task of tasks)
|
|
319
|
-
const
|
|
378
|
+
for (const task of tasks){
|
|
379
|
+
const taskAC = new AbortController();
|
|
380
|
+
const timeoutMs = task.timeout ?? 1500000;
|
|
381
|
+
const timeoutId = setTimeout(()=>{
|
|
382
|
+
console.log(`[CLI] Task ${task.taskId} timed out after ${timeoutMs}ms`);
|
|
383
|
+
taskAC.abort();
|
|
384
|
+
}, timeoutMs);
|
|
385
|
+
const onGlobalAbort = ()=>taskAC.abort();
|
|
386
|
+
abortController.signal.addEventListener('abort', onGlobalAbort);
|
|
387
|
+
const taskAgent = new agent_sdk_namespaceObject.GUIAgent({
|
|
388
|
+
model: {
|
|
389
|
+
id: config.model,
|
|
390
|
+
provider: config.provider,
|
|
391
|
+
baseURL: config.baseURL,
|
|
392
|
+
apiKey: config.apiKey
|
|
393
|
+
},
|
|
394
|
+
operator: targetOperator,
|
|
395
|
+
systemPrompt: systemPrompts.join('\n\n'),
|
|
396
|
+
signal: taskAC.signal
|
|
397
|
+
});
|
|
398
|
+
let resultEvent;
|
|
399
|
+
const startTime = Date.now();
|
|
400
|
+
try {
|
|
401
|
+
console.log(`[CLI] Starting task: ${task.taskId} at ${new Date(startTime).toISOString()}`);
|
|
402
|
+
resultEvent = await taskAgent.run(task.query);
|
|
403
|
+
} catch (taskErr) {
|
|
404
|
+
if (taskAC.signal.aborted) {
|
|
405
|
+
console.warn(`[CLI] Task ${task.taskId} was aborted (Timeout or SIGINT).`);
|
|
406
|
+
resultEvent = {
|
|
407
|
+
content: 'Task aborted or timed out'
|
|
408
|
+
};
|
|
409
|
+
} else {
|
|
410
|
+
console.error(`[CLI] Task failed: ${task.taskId}`, taskErr);
|
|
411
|
+
resultEvent = {
|
|
412
|
+
content: `Error: ${taskErr.message}`
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
} finally{
|
|
416
|
+
clearTimeout(timeoutId);
|
|
417
|
+
abortController.signal.removeEventListener('abort', onGlobalAbort);
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
const endTime = Date.now();
|
|
421
|
+
const duration = endTime - startTime;
|
|
422
|
+
const eventStream = taskAgent.getEventStream();
|
|
423
|
+
const allEvents = eventStream.getEvents();
|
|
424
|
+
const runStartEvents = allEvents.filter((e)=>'agent_run_start' === e.type);
|
|
425
|
+
const lastRunStart = runStartEvents[runStartEvents.length - 1];
|
|
426
|
+
const startIndex = allEvents.findIndex((e)=>e.id === (null == lastRunStart ? void 0 : lastRunStart.id));
|
|
427
|
+
const endIndex = allEvents.findIndex((e, idx)=>idx > startIndex && 'agent_run_end' === e.type);
|
|
428
|
+
const rangeEvents = startIndex >= 0 ? endIndex >= 0 ? allEvents.slice(startIndex, endIndex + 1) : allEvents.slice(startIndex) : allEvents;
|
|
429
|
+
const envEvents = rangeEvents.filter((e)=>'environment_input' === e.type);
|
|
430
|
+
const screenshotEvents = envEvents.filter((e)=>e.metadata && 'screenshot' === e.metadata.type);
|
|
431
|
+
let videoPath = '';
|
|
432
|
+
if (screenshotEvents.length > 0) {
|
|
433
|
+
const tempDir = external_node_path_default().join(external_node_os_default().tmpdir(), 'gui-agent-rec', task.taskId);
|
|
434
|
+
try {
|
|
435
|
+
external_node_fs_default().mkdirSync(tempDir, {
|
|
436
|
+
recursive: true
|
|
437
|
+
});
|
|
438
|
+
const validFrames = [];
|
|
439
|
+
let frameCount = 0;
|
|
440
|
+
for (const event of screenshotEvents)if (Array.isArray(event.content)) {
|
|
441
|
+
var _imgPart_image_url;
|
|
442
|
+
const imgPart = event.content.find((c)=>'image_url' === c.type && c.image_url && c.image_url.url);
|
|
443
|
+
const dataUri = null == imgPart ? void 0 : null == (_imgPart_image_url = imgPart.image_url) ? void 0 : _imgPart_image_url.url;
|
|
444
|
+
if (dataUri && 'string' == typeof dataUri && dataUri.startsWith('data:')) {
|
|
445
|
+
const commaIndex = dataUri.indexOf(',');
|
|
446
|
+
const base64Data = commaIndex >= 0 ? dataUri.substring(commaIndex + 1) : dataUri;
|
|
447
|
+
const buffer = Buffer.from(base64Data, 'base64');
|
|
448
|
+
if (buffer.length > 0) {
|
|
449
|
+
const extension = 0xff === buffer[0] && 0xd8 === buffer[1] && 0xff === buffer[2] ? 'jpg' : 'png';
|
|
450
|
+
const fileName = `${String(frameCount).padStart(4, '0')}.${extension}`;
|
|
451
|
+
const framePath = external_node_path_default().join(tempDir, fileName);
|
|
452
|
+
external_node_fs_default().writeFileSync(framePath, buffer);
|
|
453
|
+
validFrames.push({
|
|
454
|
+
file: fileName,
|
|
455
|
+
timestamp: event.timestamp || Date.now()
|
|
456
|
+
});
|
|
457
|
+
frameCount++;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (validFrames.length > 0) {
|
|
462
|
+
const concatFilePath = external_node_path_default().join(tempDir, 'filelist.txt');
|
|
463
|
+
let fileContent = '';
|
|
464
|
+
const hasTimestamps = validFrames.some((f, i)=>i > 0 && f.timestamp !== validFrames[0].timestamp);
|
|
465
|
+
for(let i = 0; i < validFrames.length; i++){
|
|
466
|
+
const frame = validFrames[i];
|
|
467
|
+
let duration = 1.0;
|
|
468
|
+
if (hasTimestamps && i < validFrames.length - 1) {
|
|
469
|
+
const diff = (validFrames[i + 1].timestamp - frame.timestamp) / 1000;
|
|
470
|
+
if (diff > 0.1 && diff < 60) duration = diff;
|
|
471
|
+
} else if (i === validFrames.length - 1) duration = 2.0;
|
|
472
|
+
fileContent += `file '${frame.file}'\n`;
|
|
473
|
+
fileContent += `duration ${duration.toFixed(3)}\n`;
|
|
474
|
+
}
|
|
475
|
+
if (validFrames.length > 0) fileContent += `file '${validFrames[validFrames.length - 1].file}'\n`;
|
|
476
|
+
external_node_fs_default().writeFileSync(concatFilePath, fileContent);
|
|
477
|
+
const outputVideoPath = external_node_path_default().join(targetOutputDir, `${task.taskId}.mp4`);
|
|
478
|
+
console.log(`[CLI] Generating video recording: ${outputVideoPath}`);
|
|
479
|
+
await new Promise((resolve, reject)=>{
|
|
480
|
+
external_fluent_ffmpeg_default()().input(concatFilePath).inputOptions([
|
|
481
|
+
'-f',
|
|
482
|
+
'concat',
|
|
483
|
+
'-safe',
|
|
484
|
+
'0'
|
|
485
|
+
]).output(outputVideoPath).outputOptions([
|
|
486
|
+
'-c:v',
|
|
487
|
+
'libx264',
|
|
488
|
+
'-pix_fmt',
|
|
489
|
+
'yuv420p',
|
|
490
|
+
'-vf',
|
|
491
|
+
'scale=trunc(iw/2)*2:trunc(ih/2)*2'
|
|
492
|
+
]).on('start', (cmd)=>console.log(`[CLI] Ffmpeg command: ${cmd}`)).on('stderr', (line)=>console.log(`[CLI] Ffmpeg stderr: ${line}`)).on('end', ()=>resolve()).on('error', (err)=>{
|
|
493
|
+
console.error('[CLI] Ffmpeg error:', err);
|
|
494
|
+
reject(err);
|
|
495
|
+
}).run();
|
|
496
|
+
});
|
|
497
|
+
videoPath = outputVideoPath;
|
|
498
|
+
console.log(`[CLI] Video saved: ${videoPath}`);
|
|
499
|
+
}
|
|
500
|
+
} catch (recErr) {
|
|
501
|
+
console.warn('[CLI] Failed to generate video recording', recErr);
|
|
502
|
+
} finally{
|
|
503
|
+
try {
|
|
504
|
+
external_node_fs_default().rmSync(tempDir, {
|
|
505
|
+
recursive: true,
|
|
506
|
+
force: true
|
|
507
|
+
});
|
|
508
|
+
} catch (_) {}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
const lastScreenshot = screenshotEvents.length > 0 ? screenshotEvents[screenshotEvents.length - 1] : null;
|
|
512
|
+
let resultPicPath = '';
|
|
513
|
+
if (lastScreenshot && Array.isArray(lastScreenshot.content)) {
|
|
514
|
+
var _imgPart_image_url1;
|
|
515
|
+
const imgPart = lastScreenshot.content.find((c)=>'image_url' === c.type && c.image_url && c.image_url.url);
|
|
516
|
+
const dataUri = null == imgPart ? void 0 : null == (_imgPart_image_url1 = imgPart.image_url) ? void 0 : _imgPart_image_url1.url;
|
|
517
|
+
if (dataUri && 'string' == typeof dataUri && dataUri.startsWith('data:')) {
|
|
518
|
+
const commaIndex = dataUri.indexOf(',');
|
|
519
|
+
const base64Data = commaIndex >= 0 ? dataUri.substring(commaIndex + 1) : dataUri;
|
|
520
|
+
const buffer = Buffer.from(base64Data, 'base64');
|
|
521
|
+
resultPicPath = external_node_path_default().join(targetOutputDir, `${task.taskId}.png`);
|
|
522
|
+
external_node_fs_default().writeFileSync(resultPicPath, buffer);
|
|
523
|
+
console.log(`[CLI] Screenshot saved: ${resultPicPath}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
if (!resultPicPath) console.log('[CLI] No screenshot captured; resultPic will be empty.');
|
|
527
|
+
const conversationLogPath = saveConversationLog(rangeEvents, targetOutputDir, task.taskId);
|
|
528
|
+
const finalAnswer = (null == resultEvent ? void 0 : resultEvent.content) ?? '';
|
|
529
|
+
const report = {
|
|
530
|
+
taskId: task.taskId,
|
|
531
|
+
taskContent: task.query,
|
|
532
|
+
startTime,
|
|
533
|
+
endTime,
|
|
534
|
+
duration,
|
|
535
|
+
resultPic: resultPicPath,
|
|
536
|
+
video: videoPath || null,
|
|
537
|
+
conversationLog: conversationLogPath,
|
|
538
|
+
finalAnswer
|
|
539
|
+
};
|
|
540
|
+
const reportPath = external_node_path_default().join(targetOutputDir, `${task.taskId}.json`);
|
|
541
|
+
external_node_fs_default().writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
542
|
+
console.log(`Result saved: ${reportPath}`);
|
|
543
|
+
console.log(`[CLI] Report JSON path: ${reportPath}`);
|
|
544
|
+
} catch (reportErr) {
|
|
545
|
+
console.warn(`[CLI] Failed to save report for task ${task.taskId}`, reportErr);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
let resultEvent;
|
|
551
|
+
const startTime = Date.now();
|
|
552
|
+
let isReportSaved = false;
|
|
553
|
+
const saveSingleTaskReport = async (finalAnswer)=>{
|
|
554
|
+
if (isReportSaved) return;
|
|
555
|
+
isReportSaved = true;
|
|
556
|
+
const endTime = Date.now();
|
|
557
|
+
const duration = endTime - startTime;
|
|
558
|
+
try {
|
|
320
559
|
const eventStream = guiAgent.getEventStream();
|
|
321
560
|
const allEvents = eventStream.getEvents();
|
|
322
561
|
const runStartEvents = allEvents.filter((e)=>'agent_run_start' === e.type);
|
|
323
|
-
const
|
|
324
|
-
const
|
|
325
|
-
const endIndex = allEvents.findIndex((e, idx)=>idx > startIndex && 'agent_run_end' === e.type);
|
|
326
|
-
const rangeEvents = startIndex >= 0 ? endIndex >= 0 ? allEvents.slice(startIndex, endIndex + 1) : allEvents.slice(startIndex) : allEvents;
|
|
327
|
-
const envEvents = rangeEvents.filter((e)=>'environment_input' === e.type);
|
|
562
|
+
const sessionId = runStartEvents.length > 0 ? runStartEvents[runStartEvents.length - 1].sessionId : `${Date.now()}`;
|
|
563
|
+
const envEvents = allEvents.filter((e)=>'environment_input' === e.type);
|
|
328
564
|
const screenshotEvents = envEvents.filter((e)=>e.metadata && 'screenshot' === e.metadata.type);
|
|
329
565
|
const lastScreenshot = screenshotEvents.length > 0 ? screenshotEvents[screenshotEvents.length - 1] : null;
|
|
566
|
+
const targetOutputDir = options.output ? external_node_path_default().resolve(options.output) : external_node_path_default().join(external_node_os_default().homedir(), '.gui-agent-results');
|
|
567
|
+
console.log(`[CLI] Output directory (resolved): ${targetOutputDir}`);
|
|
568
|
+
external_node_fs_default().mkdirSync(targetOutputDir, {
|
|
569
|
+
recursive: true
|
|
570
|
+
});
|
|
571
|
+
console.log(`[CLI] TaskId/SessionId: ${sessionId}`);
|
|
572
|
+
let videoPath = '';
|
|
573
|
+
if (screenshotEvents.length > 0) {
|
|
574
|
+
const tempDir = external_node_path_default().join(external_node_os_default().tmpdir(), 'gui-agent-rec', sessionId);
|
|
575
|
+
try {
|
|
576
|
+
external_node_fs_default().mkdirSync(tempDir, {
|
|
577
|
+
recursive: true
|
|
578
|
+
});
|
|
579
|
+
const validFrames = [];
|
|
580
|
+
let frameCount = 0;
|
|
581
|
+
for (const event of screenshotEvents)if (Array.isArray(event.content)) {
|
|
582
|
+
var _imgPart_image_url;
|
|
583
|
+
const imgPart = event.content.find((c)=>'image_url' === c.type && c.image_url && c.image_url.url);
|
|
584
|
+
const dataUri = null == imgPart ? void 0 : null == (_imgPart_image_url = imgPart.image_url) ? void 0 : _imgPart_image_url.url;
|
|
585
|
+
if (dataUri && 'string' == typeof dataUri && dataUri.startsWith('data:')) {
|
|
586
|
+
const commaIndex = dataUri.indexOf(',');
|
|
587
|
+
const base64Data = commaIndex >= 0 ? dataUri.substring(commaIndex + 1) : dataUri;
|
|
588
|
+
const buffer = Buffer.from(base64Data, 'base64');
|
|
589
|
+
if (buffer.length > 0) {
|
|
590
|
+
const extension = 0xff === buffer[0] && 0xd8 === buffer[1] && 0xff === buffer[2] ? 'jpg' : 'png';
|
|
591
|
+
const fileName = `${String(frameCount).padStart(4, '0')}.${extension}`;
|
|
592
|
+
const framePath = external_node_path_default().join(tempDir, fileName);
|
|
593
|
+
external_node_fs_default().writeFileSync(framePath, buffer);
|
|
594
|
+
validFrames.push({
|
|
595
|
+
file: fileName,
|
|
596
|
+
timestamp: event.timestamp || Date.now()
|
|
597
|
+
});
|
|
598
|
+
frameCount++;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
if (validFrames.length > 0) {
|
|
603
|
+
const concatFilePath = external_node_path_default().join(tempDir, 'filelist.txt');
|
|
604
|
+
let fileContent = '';
|
|
605
|
+
const hasTimestamps = validFrames.some((f, i)=>i > 0 && f.timestamp !== validFrames[0].timestamp);
|
|
606
|
+
for(let i = 0; i < validFrames.length; i++){
|
|
607
|
+
const frame = validFrames[i];
|
|
608
|
+
let duration = 1.0;
|
|
609
|
+
if (hasTimestamps && i < validFrames.length - 1) {
|
|
610
|
+
const diff = (validFrames[i + 1].timestamp - frame.timestamp) / 1000;
|
|
611
|
+
if (diff > 0.1 && diff < 60) duration = diff;
|
|
612
|
+
} else if (i === validFrames.length - 1) duration = 2.0;
|
|
613
|
+
fileContent += `file '${frame.file}'\n`;
|
|
614
|
+
fileContent += `duration ${duration.toFixed(3)}\n`;
|
|
615
|
+
}
|
|
616
|
+
if (validFrames.length > 0) fileContent += `file '${validFrames[validFrames.length - 1].file}'\n`;
|
|
617
|
+
external_node_fs_default().writeFileSync(concatFilePath, fileContent);
|
|
618
|
+
const outputVideoPath = external_node_path_default().join(targetOutputDir, `${sessionId}.mp4`);
|
|
619
|
+
console.log(`[CLI] Generating video recording: ${outputVideoPath}`);
|
|
620
|
+
await new Promise((resolve, reject)=>{
|
|
621
|
+
external_fluent_ffmpeg_default()().input(concatFilePath).inputOptions([
|
|
622
|
+
'-f',
|
|
623
|
+
'concat',
|
|
624
|
+
'-safe',
|
|
625
|
+
'0'
|
|
626
|
+
]).output(outputVideoPath).outputOptions([
|
|
627
|
+
'-c:v',
|
|
628
|
+
'libx264',
|
|
629
|
+
'-pix_fmt',
|
|
630
|
+
'yuv420p',
|
|
631
|
+
'-vf',
|
|
632
|
+
'scale=trunc(iw/2)*2:trunc(ih/2)*2'
|
|
633
|
+
]).on('start', (cmd)=>console.log(`[CLI] Ffmpeg command: ${cmd}`)).on('stderr', (line)=>console.log(`[CLI] Ffmpeg stderr: ${line}`)).on('end', ()=>resolve()).on('error', (err)=>{
|
|
634
|
+
console.error('[CLI] Ffmpeg error:', err);
|
|
635
|
+
reject(err);
|
|
636
|
+
}).run();
|
|
637
|
+
});
|
|
638
|
+
videoPath = outputVideoPath;
|
|
639
|
+
console.log(`[CLI] Video saved: ${videoPath}`);
|
|
640
|
+
}
|
|
641
|
+
} catch (recErr) {
|
|
642
|
+
console.warn('[CLI] Failed to generate video recording', recErr);
|
|
643
|
+
} finally{
|
|
644
|
+
try {
|
|
645
|
+
external_node_fs_default().rmSync(tempDir, {
|
|
646
|
+
recursive: true,
|
|
647
|
+
force: true
|
|
648
|
+
});
|
|
649
|
+
} catch (_) {}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
330
652
|
let resultPicPath = '';
|
|
331
653
|
if (lastScreenshot && Array.isArray(lastScreenshot.content)) {
|
|
332
|
-
var
|
|
654
|
+
var _imgPart_image_url1;
|
|
333
655
|
const imgPart = lastScreenshot.content.find((c)=>'image_url' === c.type && c.image_url && c.image_url.url);
|
|
334
|
-
const dataUri = null == imgPart ? void 0 : null == (
|
|
656
|
+
const dataUri = null == imgPart ? void 0 : null == (_imgPart_image_url1 = imgPart.image_url) ? void 0 : _imgPart_image_url1.url;
|
|
335
657
|
if (dataUri && 'string' == typeof dataUri && dataUri.startsWith('data:')) {
|
|
336
658
|
const commaIndex = dataUri.indexOf(',');
|
|
337
659
|
const base64Data = commaIndex >= 0 ? dataUri.substring(commaIndex + 1) : dataUri;
|
|
338
660
|
const buffer = Buffer.from(base64Data, 'base64');
|
|
339
|
-
resultPicPath = external_node_path_default().join(targetOutputDir, `${
|
|
661
|
+
resultPicPath = external_node_path_default().join(targetOutputDir, `${sessionId}.png`);
|
|
340
662
|
external_node_fs_default().writeFileSync(resultPicPath, buffer);
|
|
341
663
|
console.log(`[CLI] Screenshot saved: ${resultPicPath}`);
|
|
342
664
|
}
|
|
343
665
|
}
|
|
344
666
|
if (!resultPicPath) console.log('[CLI] No screenshot captured; resultPic will be empty.');
|
|
345
|
-
const
|
|
667
|
+
const conversationLogPath = saveConversationLog(allEvents, targetOutputDir, sessionId);
|
|
346
668
|
const report = {
|
|
347
|
-
taskId:
|
|
669
|
+
taskId: sessionId,
|
|
670
|
+
taskContent: answers.instruction || options.query,
|
|
671
|
+
startTime,
|
|
672
|
+
endTime,
|
|
673
|
+
duration,
|
|
348
674
|
resultPic: resultPicPath,
|
|
675
|
+
video: videoPath || null,
|
|
676
|
+
conversationLog: conversationLogPath,
|
|
349
677
|
finalAnswer
|
|
350
678
|
};
|
|
351
|
-
const reportPath = external_node_path_default().join(targetOutputDir, `${
|
|
679
|
+
const reportPath = external_node_path_default().join(targetOutputDir, `${sessionId}.json`);
|
|
352
680
|
external_node_fs_default().writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
353
681
|
console.log(`Result saved: ${reportPath}`);
|
|
354
682
|
console.log(`[CLI] Report JSON path: ${reportPath}`);
|
|
355
|
-
} catch (
|
|
356
|
-
console.
|
|
683
|
+
} catch (err) {
|
|
684
|
+
console.warn('Failed to generate result report:', err);
|
|
357
685
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
686
|
+
};
|
|
687
|
+
process.removeAllListeners('SIGINT');
|
|
688
|
+
process.on('SIGINT', async ()=>{
|
|
689
|
+
console.log('\n[CLI] Received SIGINT. Saving report and exiting...');
|
|
690
|
+
abortController.abort();
|
|
691
|
+
await saveSingleTaskReport("\u7528\u6237\u5DF2\u624B\u52A8\u7EC8\u6B62");
|
|
692
|
+
process.exit(0);
|
|
693
|
+
});
|
|
361
694
|
try {
|
|
362
695
|
console.log('[CLI] Starting GUIAgent run with instruction:', answers.instruction || options.query);
|
|
363
696
|
resultEvent = await guiAgent.run(answers.instruction);
|
|
364
697
|
console.log('[CLI] GUIAgent run completed.');
|
|
365
698
|
} catch (err) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
try {
|
|
382
|
-
const eventStream = guiAgent.getEventStream();
|
|
383
|
-
const allEvents = eventStream.getEvents();
|
|
384
|
-
const runStartEvents = allEvents.filter((e)=>'agent_run_start' === e.type);
|
|
385
|
-
const sessionId = runStartEvents.length > 0 ? runStartEvents[runStartEvents.length - 1].sessionId : `${Date.now()}`;
|
|
386
|
-
const envEvents = allEvents.filter((e)=>'environment_input' === e.type);
|
|
387
|
-
const screenshotEvents = envEvents.filter((e)=>e.metadata && 'screenshot' === e.metadata.type);
|
|
388
|
-
const lastScreenshot = screenshotEvents.length > 0 ? screenshotEvents[screenshotEvents.length - 1] : null;
|
|
389
|
-
const targetOutputDir = options.output ? external_node_path_default().resolve(options.output) : external_node_path_default().join(external_node_os_default().homedir(), '.gui-agent-results');
|
|
390
|
-
console.log(`[CLI] Output directory (resolved): ${targetOutputDir}`);
|
|
391
|
-
external_node_fs_default().mkdirSync(targetOutputDir, {
|
|
392
|
-
recursive: true
|
|
393
|
-
});
|
|
394
|
-
console.log(`[CLI] TaskId/SessionId: ${sessionId}`);
|
|
395
|
-
let resultPicPath = '';
|
|
396
|
-
if (lastScreenshot && Array.isArray(lastScreenshot.content)) {
|
|
397
|
-
var _imgPart_image_url1;
|
|
398
|
-
const imgPart = lastScreenshot.content.find((c)=>'image_url' === c.type && c.image_url && c.image_url.url);
|
|
399
|
-
const dataUri = null == imgPart ? void 0 : null == (_imgPart_image_url1 = imgPart.image_url) ? void 0 : _imgPart_image_url1.url;
|
|
400
|
-
if (dataUri && 'string' == typeof dataUri && dataUri.startsWith('data:')) {
|
|
401
|
-
const commaIndex = dataUri.indexOf(',');
|
|
402
|
-
const base64Data = commaIndex >= 0 ? dataUri.substring(commaIndex + 1) : dataUri;
|
|
403
|
-
const buffer = Buffer.from(base64Data, 'base64');
|
|
404
|
-
resultPicPath = external_node_path_default().join(targetOutputDir, `${sessionId}.png`);
|
|
405
|
-
external_node_fs_default().writeFileSync(resultPicPath, buffer);
|
|
406
|
-
console.log(`[CLI] Screenshot saved: ${resultPicPath}`);
|
|
699
|
+
if ('AbortError' === err.name || abortController.signal.aborted) console.log('[CLI] GUIAgent run aborted.');
|
|
700
|
+
else {
|
|
701
|
+
var _err_response, _err_response1;
|
|
702
|
+
console.error('[CLI] GUIAgent run failed.');
|
|
703
|
+
const errMsg = (null == err ? void 0 : err.message) || String(err);
|
|
704
|
+
console.error('[CLI] Error message:', errMsg);
|
|
705
|
+
if (null == err ? void 0 : err.status) console.error('[CLI] HTTP status:', err.status);
|
|
706
|
+
if (null == err ? void 0 : err.code) console.error('[CLI] Error code:', err.code);
|
|
707
|
+
const respData = (null == err ? void 0 : null == (_err_response = err.response) ? void 0 : _err_response.data) || (null == err ? void 0 : null == (_err_response1 = err.response) ? void 0 : _err_response1.body) || (null == err ? void 0 : err.data);
|
|
708
|
+
if (respData) try {
|
|
709
|
+
const text = 'string' == typeof respData ? respData : JSON.stringify(respData);
|
|
710
|
+
console.error('[CLI] Response body:', text.slice(0, 500));
|
|
711
|
+
} catch (_) {
|
|
712
|
+
console.error('[CLI] Response body: [unprintable]');
|
|
407
713
|
}
|
|
408
714
|
}
|
|
409
|
-
if (!resultPicPath) console.log('[CLI] No screenshot captured; resultPic will be empty.');
|
|
410
|
-
const finalAnswer = (null == resultEvent ? void 0 : resultEvent.content) ?? '';
|
|
411
|
-
const report = {
|
|
412
|
-
taskId: sessionId,
|
|
413
|
-
resultPic: resultPicPath,
|
|
414
|
-
finalAnswer
|
|
415
|
-
};
|
|
416
|
-
const reportPath = external_node_path_default().join(targetOutputDir, `${sessionId}.json`);
|
|
417
|
-
external_node_fs_default().writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
418
|
-
console.log(`Result saved: ${reportPath}`);
|
|
419
|
-
console.log(`[CLI] Report JSON path: ${reportPath}`);
|
|
420
|
-
} catch (err) {
|
|
421
|
-
console.warn('Failed to generate result report:', err);
|
|
422
715
|
}
|
|
716
|
+
await saveSingleTaskReport((null == resultEvent ? void 0 : resultEvent.content) ?? '');
|
|
423
717
|
};
|
|
424
718
|
const resetConfig = async (configPath)=>{
|
|
425
719
|
const CONFIG_PATH = configPath || external_node_path_default().join(external_node_os_default().homedir(), '.gui-agent-cli.json');
|