@aiscene/shared 8.0.2 → 8.0.4
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/agent-tools/agent-behavior-init-args.mjs +44 -0
- package/dist/es/agent-tools/base-tools.mjs +163 -0
- package/dist/es/agent-tools/chrome-path.mjs +50 -0
- package/dist/es/agent-tools/cli-report-session.mjs +78 -0
- package/dist/es/agent-tools/error-formatter.mjs +106 -0
- package/dist/es/agent-tools/index.mjs +9 -0
- package/dist/es/agent-tools/init-arg-utils.mjs +38 -0
- package/dist/es/agent-tools/observation-artifact.mjs +5 -0
- package/dist/es/agent-tools/observation-record.mjs +248 -0
- package/dist/es/agent-tools/tool-defaults.mjs +54 -0
- package/dist/es/agent-tools/tool-generator.mjs +529 -0
- package/dist/es/agent-tools/types.mjs +3 -0
- package/dist/es/agent-tools/user-prompt.mjs +66 -0
- 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/cli/interrupt.mjs +116 -0
- package/dist/es/cli/record-command.mjs +130 -0
- package/dist/es/cli/screenshot-file.mjs +24 -0
- package/dist/es/cli/verbose-ai-act.mjs +230 -0
- package/dist/es/cli/verbose-screenshot.mjs +134 -0
- package/dist/es/cli/verbose.mjs +404 -0
- 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 +4 -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 +58 -17
- package/dist/es/img/photon-loader.mjs +4 -0
- 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/es/recorder.mjs +249 -0
- package/dist/lib/agent-tools/agent-behavior-init-args.js +87 -0
- package/dist/lib/agent-tools/base-tools.js +197 -0
- package/dist/lib/agent-tools/chrome-path.js +87 -0
- package/dist/lib/agent-tools/cli-report-session.js +121 -0
- package/dist/lib/agent-tools/error-formatter.js +149 -0
- package/dist/lib/agent-tools/index.js +114 -0
- package/dist/lib/agent-tools/init-arg-utils.js +78 -0
- package/dist/lib/agent-tools/observation-artifact.js +42 -0
- package/dist/lib/agent-tools/observation-record.js +297 -0
- package/dist/lib/agent-tools/tool-defaults.js +97 -0
- package/dist/lib/agent-tools/tool-generator.js +569 -0
- package/dist/lib/agent-tools/types.js +40 -0
- package/dist/lib/agent-tools/user-prompt.js +103 -0
- 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/cli/interrupt.js +156 -0
- package/dist/lib/cli/record-command.js +164 -0
- package/dist/lib/cli/screenshot-file.js +58 -0
- package/dist/lib/cli/verbose-ai-act.js +273 -0
- package/dist/lib/cli/verbose-screenshot.js +177 -0
- package/dist/lib/cli/verbose.js +465 -0
- 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 +9 -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 +65 -18
- package/dist/lib/img/photon-loader.js +38 -0
- 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/lib/recorder.js +307 -0
- package/dist/types/agent-tools/agent-behavior-init-args.d.ts +17 -0
- package/dist/types/agent-tools/base-tools.d.ts +158 -0
- package/dist/types/agent-tools/chrome-path.d.ts +2 -0
- package/dist/types/agent-tools/cli-report-session.d.ts +12 -0
- package/dist/types/agent-tools/error-formatter.d.ts +30 -0
- package/dist/types/agent-tools/index.d.ts +9 -0
- package/dist/types/agent-tools/init-arg-utils.d.ts +13 -0
- package/dist/types/agent-tools/observation-artifact.d.ts +10 -0
- package/dist/types/agent-tools/observation-record.d.ts +38 -0
- package/dist/types/agent-tools/tool-defaults.d.ts +63 -0
- package/dist/types/agent-tools/tool-generator.d.ts +13 -0
- package/dist/types/agent-tools/types.d.ts +213 -0
- package/dist/types/agent-tools/user-prompt.d.ts +13 -0
- 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/cli/interrupt.d.ts +49 -0
- package/dist/types/cli/record-command.d.ts +3 -0
- package/dist/types/cli/screenshot-file.d.ts +10 -0
- package/dist/types/cli/verbose-ai-act.d.ts +44 -0
- package/dist/types/cli/verbose-screenshot.d.ts +10 -0
- package/dist/types/cli/verbose.d.ts +40 -0
- 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 +14 -5
- 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 +7 -0
- package/dist/types/img/photon-loader.d.ts +2 -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 +10 -0
- package/dist/types/recorder.d.ts +113 -0
- package/package.json +1 -1
- package/src/agent-tools/agent-behavior-init-args.ts +109 -0
- package/src/agent-tools/base-tools.ts +399 -0
- package/src/agent-tools/chrome-path.ts +74 -0
- package/src/agent-tools/cli-report-session.ts +130 -0
- package/src/agent-tools/error-formatter.ts +177 -0
- package/src/agent-tools/index.ts +9 -0
- package/src/agent-tools/init-arg-utils.ts +105 -0
- package/src/agent-tools/observation-artifact.ts +29 -0
- package/src/agent-tools/observation-record.ts +331 -0
- package/src/agent-tools/tool-defaults.ts +119 -0
- package/src/agent-tools/tool-generator.ts +866 -0
- package/src/agent-tools/types.ts +250 -0
- package/src/agent-tools/user-prompt.ts +102 -0
- 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/cli/interrupt.ts +207 -0
- package/src/cli/record-command.ts +177 -0
- package/src/cli/screenshot-file.ts +61 -0
- package/src/cli/verbose-ai-act.ts +387 -0
- package/src/cli/verbose-screenshot.ts +269 -0
- package/src/cli/verbose.ts +753 -0
- 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 +13 -2
- package/src/env/utils.ts +0 -50
- package/src/extractor/index.ts +1 -1
- package/src/img/index.ts +14 -0
- package/src/img/info.ts +97 -45
- package/src/img/photon-loader.ts +5 -0
- package/src/img/transform.ts +261 -2
- 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 +18 -1
- package/src/recorder.ts +625 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const agentBehaviorInitArgShape = {
|
|
3
|
+
aiActContext: z.string().optional().describe('Background knowledge passed to aiAct. Default: no extra context.'),
|
|
4
|
+
replanningCycleLimit: z.number().int().nonnegative().optional().describe('Maximum number of replanning cycles for aiAct. Default: model adapter default.'),
|
|
5
|
+
waitAfterAction: z.number().nonnegative().optional().describe('Wait time in milliseconds after each action execution. Default: 300ms.'),
|
|
6
|
+
screenshotShrinkFactor: z.number().min(1).optional().describe('Screenshot shrink factor before sending images to AI. Default: 1; high values may reduce recognition quality, especially on mobile.')
|
|
7
|
+
};
|
|
8
|
+
function extractAgentBehaviorInitArgs(extracted) {
|
|
9
|
+
if (!extracted) return;
|
|
10
|
+
const agentOptions = {
|
|
11
|
+
...'string' == typeof extracted.aiActContext ? {
|
|
12
|
+
aiActContext: extracted.aiActContext
|
|
13
|
+
} : {},
|
|
14
|
+
...'string' == typeof extracted.aiActionContext ? {
|
|
15
|
+
aiActionContext: extracted.aiActionContext
|
|
16
|
+
} : {},
|
|
17
|
+
...'number' == typeof extracted.replanningCycleLimit ? {
|
|
18
|
+
replanningCycleLimit: extracted.replanningCycleLimit
|
|
19
|
+
} : {},
|
|
20
|
+
...'number' == typeof extracted.waitAfterAction ? {
|
|
21
|
+
waitAfterAction: extracted.waitAfterAction
|
|
22
|
+
} : {},
|
|
23
|
+
...'number' == typeof extracted.screenshotShrinkFactor ? {
|
|
24
|
+
screenshotShrinkFactor: extracted.screenshotShrinkFactor
|
|
25
|
+
} : {}
|
|
26
|
+
};
|
|
27
|
+
return Object.keys(agentOptions).length > 0 ? agentOptions : void 0;
|
|
28
|
+
}
|
|
29
|
+
function stableJsonValue(value) {
|
|
30
|
+
if (Array.isArray(value)) return value.map(stableJsonValue);
|
|
31
|
+
if (value && 'object' == typeof value) return Object.fromEntries(Object.entries(value).sort(([left], [right])=>left.localeCompare(right)).map(([key, nestedValue])=>[
|
|
32
|
+
key,
|
|
33
|
+
stableJsonValue(nestedValue)
|
|
34
|
+
]));
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
function getAgentInitArgsSignature(initArgs) {
|
|
38
|
+
if (!initArgs || 0 === Object.keys(initArgs).length) return;
|
|
39
|
+
return JSON.stringify(stableJsonValue(initArgs));
|
|
40
|
+
}
|
|
41
|
+
function shouldRebuildAgentForInitArgs(currentSignature, nextSignature) {
|
|
42
|
+
return currentSignature !== nextSignature && (void 0 !== currentSignature || void 0 !== nextSignature);
|
|
43
|
+
}
|
|
44
|
+
export { agentBehaviorInitArgShape, extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { parseBase64 } from "@aiscene/shared/img";
|
|
2
|
+
import { getDebug } from "@aiscene/shared/logger";
|
|
3
|
+
import { createRecordCliCommand } from "../cli/record-command.mjs";
|
|
4
|
+
import { camelToKebab, getKeyAliases } from "../key-alias-utils.mjs";
|
|
5
|
+
import { generateCliReportSession, readCliReportSession, writeCliReportSession } from "./cli-report-session.mjs";
|
|
6
|
+
import { createNamespacedInitArgSchema, extractNamespacedArgs, sanitizeNamespacedArgs } from "./init-arg-utils.mjs";
|
|
7
|
+
import { mergeToolDefaults } from "./tool-defaults.mjs";
|
|
8
|
+
import { generateCommonTools, generateToolsFromActionSpace } from "./tool-generator.mjs";
|
|
9
|
+
function _define_property(obj, key, value) {
|
|
10
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
11
|
+
value: value,
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true
|
|
15
|
+
});
|
|
16
|
+
else obj[key] = value;
|
|
17
|
+
return obj;
|
|
18
|
+
}
|
|
19
|
+
const debug = getDebug('agent-tools:base-tools');
|
|
20
|
+
class BaseMidsceneTools {
|
|
21
|
+
getInitArgKeys() {
|
|
22
|
+
return this.initArgSpec ? Object.keys(this.initArgSpec.shape) : [];
|
|
23
|
+
}
|
|
24
|
+
extractAgentInitParam(args) {
|
|
25
|
+
if (!this.initArgSpec) return;
|
|
26
|
+
const extracted = extractNamespacedArgs(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
27
|
+
if (this.initArgSpec.adapt) return this.initArgSpec.adapt(extracted);
|
|
28
|
+
return extracted;
|
|
29
|
+
}
|
|
30
|
+
sanitizeToolArgs(args) {
|
|
31
|
+
if (!this.initArgSpec) return args;
|
|
32
|
+
return sanitizeNamespacedArgs(args, this.initArgSpec.namespace, this.getInitArgKeys());
|
|
33
|
+
}
|
|
34
|
+
getAgentInitArgSchema() {
|
|
35
|
+
if (!this.initArgSpec) return {};
|
|
36
|
+
return createNamespacedInitArgSchema(this.initArgSpec.namespace, this.initArgSpec.shape);
|
|
37
|
+
}
|
|
38
|
+
getAgentInitArgCliMetadata() {
|
|
39
|
+
if (!this.initArgSpec?.cli) return;
|
|
40
|
+
const options = Object.fromEntries(this.getInitArgKeys().map((key)=>{
|
|
41
|
+
const canonicalKey = `${this.initArgSpec.namespace}.${key}`;
|
|
42
|
+
const preferredName = this.initArgSpec.cli?.preferredNames?.[key] ?? (this.initArgSpec.cli?.preferBareKeys ? camelToKebab(key) : canonicalKey);
|
|
43
|
+
const acceptedNames = new Set([
|
|
44
|
+
preferredName,
|
|
45
|
+
...this.initArgSpec.cli?.preferBareKeys ? getKeyAliases(key) : getKeyAliases(canonicalKey)
|
|
46
|
+
]);
|
|
47
|
+
acceptedNames.delete(preferredName);
|
|
48
|
+
return [
|
|
49
|
+
canonicalKey,
|
|
50
|
+
{
|
|
51
|
+
preferredName,
|
|
52
|
+
aliases: [
|
|
53
|
+
...acceptedNames
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
}));
|
|
58
|
+
return {
|
|
59
|
+
options
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
preparePlatformTools() {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
getCliReportSessionName() {}
|
|
66
|
+
createNewCliReportSession(targetIdentity) {
|
|
67
|
+
const sessionName = this.getCliReportSessionName();
|
|
68
|
+
if (!sessionName) return;
|
|
69
|
+
return generateCliReportSession(sessionName, targetIdentity);
|
|
70
|
+
}
|
|
71
|
+
commitCliReportSession(session) {
|
|
72
|
+
if (session) writeCliReportSession(session);
|
|
73
|
+
}
|
|
74
|
+
readCliReportFileName() {
|
|
75
|
+
const sessionName = this.getCliReportSessionName();
|
|
76
|
+
if (!sessionName) return;
|
|
77
|
+
return readCliReportSession(sessionName)?.reportFileName;
|
|
78
|
+
}
|
|
79
|
+
readCliReportAgentOptions() {
|
|
80
|
+
const reportFileName = this.readCliReportFileName();
|
|
81
|
+
if (!reportFileName) return;
|
|
82
|
+
return {
|
|
83
|
+
reportFileName,
|
|
84
|
+
reportAttributes: {
|
|
85
|
+
'data-group-id': reportFileName
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async initTools() {
|
|
90
|
+
this.toolDefinitions = [];
|
|
91
|
+
const platformTools = this.preparePlatformTools();
|
|
92
|
+
this.toolDefinitions.push(...platformTools);
|
|
93
|
+
let actionSpace;
|
|
94
|
+
if (this.agent) {
|
|
95
|
+
actionSpace = await this.agent.getActionSpace();
|
|
96
|
+
debug('Action space from agent:', actionSpace.map((a)=>a.name).join(', '));
|
|
97
|
+
} else {
|
|
98
|
+
const tempDevice = this.createTemporaryDevice();
|
|
99
|
+
actionSpace = tempDevice.actionSpace();
|
|
100
|
+
await tempDevice.destroy?.();
|
|
101
|
+
debug('Action space from temporary device:', actionSpace.map((a)=>a.name).join(', '));
|
|
102
|
+
}
|
|
103
|
+
const actionTools = generateToolsFromActionSpace(actionSpace, (args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), (args = {})=>this.sanitizeToolArgs(args), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata(), this.toolDefaults);
|
|
104
|
+
const commonTools = generateCommonTools((args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata(), this.toolDefaults);
|
|
105
|
+
this.toolDefinitions.push(...actionTools, ...commonTools);
|
|
106
|
+
debug('Total tools prepared:', this.toolDefinitions.length);
|
|
107
|
+
}
|
|
108
|
+
async destroy() {
|
|
109
|
+
await this.agent?.destroy?.();
|
|
110
|
+
}
|
|
111
|
+
getToolDefinitions() {
|
|
112
|
+
return this.toolDefinitions;
|
|
113
|
+
}
|
|
114
|
+
getCliToolDefinitions() {
|
|
115
|
+
return [
|
|
116
|
+
createRecordCliCommand((args = {})=>this.ensureAgent(this.extractAgentInitParam(args)), this.getAgentInitArgSchema(), this.getAgentInitArgCliMetadata())
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
setAgent(agent) {
|
|
120
|
+
this.agent = agent;
|
|
121
|
+
}
|
|
122
|
+
setToolDefaults(toolDefaults) {
|
|
123
|
+
this.toolDefaults = mergeToolDefaults(this.toolDefaults, toolDefaults);
|
|
124
|
+
}
|
|
125
|
+
buildScreenshotContent(screenshot) {
|
|
126
|
+
const { mimeType, body } = parseBase64(screenshot);
|
|
127
|
+
return [
|
|
128
|
+
{
|
|
129
|
+
type: 'image',
|
|
130
|
+
data: body,
|
|
131
|
+
mimeType
|
|
132
|
+
}
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
buildTextResult(text) {
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: 'text',
|
|
140
|
+
text
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
createDisconnectHandler(platformName) {
|
|
146
|
+
return async ()=>{
|
|
147
|
+
if (!this.agent) return this.buildTextResult('No active connection to disconnect');
|
|
148
|
+
try {
|
|
149
|
+
await this.agent.destroy?.();
|
|
150
|
+
} catch (error) {
|
|
151
|
+
debug('Failed to destroy agent during disconnect:', error);
|
|
152
|
+
}
|
|
153
|
+
this.agent = void 0;
|
|
154
|
+
return this.buildTextResult(`Disconnected from ${platformName}`);
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
constructor(){
|
|
158
|
+
_define_property(this, "agent", void 0);
|
|
159
|
+
_define_property(this, "toolDefinitions", []);
|
|
160
|
+
_define_property(this, "toolDefaults", {});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export { BaseMidsceneTools };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { MIDSCENE_CHROME_PATH, MIDSCENE_MCP_CHROME_PATH, globalConfigManager } from "../env/index.mjs";
|
|
3
|
+
import { getDebug } from "../logger.mjs";
|
|
4
|
+
const warnChromePath = getDebug('agent-tools:chrome-path', {
|
|
5
|
+
console: true
|
|
6
|
+
});
|
|
7
|
+
let hasWarnedLegacyChromePath = false;
|
|
8
|
+
let cachedSystemChromePath;
|
|
9
|
+
function getSystemChromePath() {
|
|
10
|
+
if (void 0 !== cachedSystemChromePath) return cachedSystemChromePath;
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const chromePaths = {
|
|
13
|
+
darwin: [
|
|
14
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
15
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium'
|
|
16
|
+
],
|
|
17
|
+
win32: [
|
|
18
|
+
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
19
|
+
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
|
|
20
|
+
`C:\\Users\\${process.env.USERNAME ?? process.env.USER}\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe`
|
|
21
|
+
],
|
|
22
|
+
linux: [
|
|
23
|
+
'/opt/google/chrome/chrome',
|
|
24
|
+
'/opt/google/chrome/google-chrome',
|
|
25
|
+
'/usr/bin/google-chrome-stable',
|
|
26
|
+
'/usr/bin/google-chrome',
|
|
27
|
+
'/usr/bin/chromium-browser',
|
|
28
|
+
'/usr/bin/chromium',
|
|
29
|
+
'/snap/bin/chromium'
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
const paths = chromePaths[platform] ?? [];
|
|
33
|
+
const foundPath = paths.find((p)=>existsSync(p));
|
|
34
|
+
if (foundPath) cachedSystemChromePath = foundPath;
|
|
35
|
+
return foundPath;
|
|
36
|
+
}
|
|
37
|
+
function resolveChromePath() {
|
|
38
|
+
const primaryEnvPath = globalConfigManager.getEnvConfigValue(MIDSCENE_CHROME_PATH);
|
|
39
|
+
const legacyEnvPath = globalConfigManager.getEnvConfigValue(MIDSCENE_MCP_CHROME_PATH);
|
|
40
|
+
const envPath = primaryEnvPath || legacyEnvPath;
|
|
41
|
+
if (!primaryEnvPath && legacyEnvPath && !hasWarnedLegacyChromePath) {
|
|
42
|
+
warnChromePath('MIDSCENE_MCP_CHROME_PATH is deprecated. Use MIDSCENE_CHROME_PATH instead.');
|
|
43
|
+
hasWarnedLegacyChromePath = true;
|
|
44
|
+
}
|
|
45
|
+
if (envPath && 'auto' !== envPath && existsSync(envPath)) return envPath;
|
|
46
|
+
const systemPath = getSystemChromePath();
|
|
47
|
+
if (systemPath) return systemPath;
|
|
48
|
+
throw new Error('Chrome not found. Install Google Chrome or set MIDSCENE_CHROME_PATH environment variable.');
|
|
49
|
+
}
|
|
50
|
+
export { getSystemChromePath, resolveChromePath };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getMidsceneRunBaseDir, getMidsceneRunSubDir } from "../common.mjs";
|
|
4
|
+
const sessionDirName = 'cli-report-session';
|
|
5
|
+
function sanitizeSessionName(sessionName) {
|
|
6
|
+
return sessionName.replace(/[^a-zA-Z0-9._-]/g, '_') || 'default';
|
|
7
|
+
}
|
|
8
|
+
function sanitizeFileSegment(segment) {
|
|
9
|
+
const sanitized = segment.replace(/[^a-zA-Z0-9._-]/g, '_') || 'unknown';
|
|
10
|
+
return sanitized.slice(0, 80);
|
|
11
|
+
}
|
|
12
|
+
function ensureHtmlFileName(reportFileName) {
|
|
13
|
+
return reportFileName.endsWith('.html') ? reportFileName : `${reportFileName}.html`;
|
|
14
|
+
}
|
|
15
|
+
function formatDateForFileName(date) {
|
|
16
|
+
const pad = (value)=>String(value).padStart(2, '0');
|
|
17
|
+
const day = [
|
|
18
|
+
date.getFullYear(),
|
|
19
|
+
pad(date.getMonth() + 1),
|
|
20
|
+
pad(date.getDate())
|
|
21
|
+
].join('-');
|
|
22
|
+
const time = [
|
|
23
|
+
pad(date.getHours()),
|
|
24
|
+
pad(date.getMinutes()),
|
|
25
|
+
pad(date.getSeconds())
|
|
26
|
+
].join('-');
|
|
27
|
+
return `${day}_${time}`;
|
|
28
|
+
}
|
|
29
|
+
function randomId() {
|
|
30
|
+
return Math.random().toString(36).slice(2, 10);
|
|
31
|
+
}
|
|
32
|
+
function getCliReportSessionDir() {
|
|
33
|
+
const dir = join(getMidsceneRunBaseDir(), sessionDirName);
|
|
34
|
+
if (!existsSync(dir)) mkdirSync(dir, {
|
|
35
|
+
recursive: true
|
|
36
|
+
});
|
|
37
|
+
return dir;
|
|
38
|
+
}
|
|
39
|
+
function getCliReportSessionPath(sessionName) {
|
|
40
|
+
return join(getCliReportSessionDir(), `${sanitizeSessionName(sessionName)}.json`);
|
|
41
|
+
}
|
|
42
|
+
function generateCliReportSession(sessionName, targetIdentity) {
|
|
43
|
+
const identitySegment = targetIdentity ? `-${sanitizeFileSegment(targetIdentity)}` : '';
|
|
44
|
+
const reportFileName = `${sanitizeSessionName(sessionName)}${identitySegment}-${formatDateForFileName(new Date())}-${randomId()}`;
|
|
45
|
+
const reportPath = join(getMidsceneRunSubDir('report'), ensureHtmlFileName(reportFileName));
|
|
46
|
+
const session = {
|
|
47
|
+
version: 1,
|
|
48
|
+
sessionName,
|
|
49
|
+
...targetIdentity ? {
|
|
50
|
+
targetIdentity
|
|
51
|
+
} : {},
|
|
52
|
+
reportFileName,
|
|
53
|
+
reportPath,
|
|
54
|
+
createdAt: Date.now()
|
|
55
|
+
};
|
|
56
|
+
return session;
|
|
57
|
+
}
|
|
58
|
+
function writeCliReportSession(session) {
|
|
59
|
+
writeFileSync(getCliReportSessionPath(session.sessionName), JSON.stringify(session, null, 2), 'utf-8');
|
|
60
|
+
}
|
|
61
|
+
function createCliReportSession(sessionName, targetIdentity) {
|
|
62
|
+
const session = generateCliReportSession(sessionName, targetIdentity);
|
|
63
|
+
writeCliReportSession(session);
|
|
64
|
+
return session;
|
|
65
|
+
}
|
|
66
|
+
function readCliReportSession(sessionName) {
|
|
67
|
+
const sessionPath = getCliReportSessionPath(sessionName);
|
|
68
|
+
if (!existsSync(sessionPath)) return;
|
|
69
|
+
try {
|
|
70
|
+
const raw = readFileSync(sessionPath, 'utf-8');
|
|
71
|
+
const parsed = JSON.parse(raw);
|
|
72
|
+
if (1 !== parsed.version || parsed.sessionName !== sessionName || 'string' != typeof parsed.reportFileName || !parsed.reportFileName.trim() || /[\\/]/.test(parsed.reportFileName)) return;
|
|
73
|
+
return parsed;
|
|
74
|
+
} catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export { createCliReportSession, generateCliReportSession, readCliReportSession, writeCliReportSession };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const maxSerializedStringLength = 4096;
|
|
2
|
+
const truncatedStringSuffix = '… [truncated]';
|
|
3
|
+
function isObject(error) {
|
|
4
|
+
return 'object' == typeof error && null !== error || 'function' == typeof error;
|
|
5
|
+
}
|
|
6
|
+
function safelyReadProperty(error, key) {
|
|
7
|
+
try {
|
|
8
|
+
return Reflect.get(error, key);
|
|
9
|
+
} catch {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function readBoundedDiagnostic(error, keys) {
|
|
14
|
+
for (const key of keys){
|
|
15
|
+
const value = safelyReadProperty(error, key);
|
|
16
|
+
if ('number' == typeof value) return value;
|
|
17
|
+
if ('string' == typeof value) return truncateSerializedErrorString(value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function truncateSerializedErrorString(value) {
|
|
21
|
+
if (value.length <= maxSerializedStringLength) return value;
|
|
22
|
+
return `${value.slice(0, maxSerializedStringLength - truncatedStringSuffix.length)}${truncatedStringSuffix}`;
|
|
23
|
+
}
|
|
24
|
+
function readNonEmptyMessage(error) {
|
|
25
|
+
const message = safelyReadProperty(error, 'message');
|
|
26
|
+
return 'string' == typeof message && message ? message : void 0;
|
|
27
|
+
}
|
|
28
|
+
function extractStringMessage(error) {
|
|
29
|
+
const directMessage = readNonEmptyMessage(error);
|
|
30
|
+
if (directMessage) return directMessage;
|
|
31
|
+
for (const nestedKey of [
|
|
32
|
+
'error',
|
|
33
|
+
'cause'
|
|
34
|
+
]){
|
|
35
|
+
const nestedError = safelyReadProperty(error, nestedKey);
|
|
36
|
+
if (!isObject(nestedError)) continue;
|
|
37
|
+
const nestedMessage = readNonEmptyMessage(nestedError);
|
|
38
|
+
if (nestedMessage) return nestedMessage;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function getErrorMessage(error) {
|
|
42
|
+
const result = serializeErrorValue(error);
|
|
43
|
+
const serialized = result.error;
|
|
44
|
+
if (!isObject(error) || result.hasMessage) return serialized.message;
|
|
45
|
+
const summary = {
|
|
46
|
+
name: serialized.name,
|
|
47
|
+
message: serialized.message
|
|
48
|
+
};
|
|
49
|
+
for (const key of [
|
|
50
|
+
'code',
|
|
51
|
+
'status',
|
|
52
|
+
'requestId'
|
|
53
|
+
]){
|
|
54
|
+
const value = serialized[key];
|
|
55
|
+
if (void 0 !== value) summary[key] = value;
|
|
56
|
+
}
|
|
57
|
+
return truncateSerializedErrorString(JSON.stringify(summary));
|
|
58
|
+
}
|
|
59
|
+
function getErrorStack(error) {
|
|
60
|
+
if (!isObject(error)) return;
|
|
61
|
+
const stack = safelyReadProperty(error, 'stack');
|
|
62
|
+
return 'string' == typeof stack ? stack : void 0;
|
|
63
|
+
}
|
|
64
|
+
function serializeErrorValue(error) {
|
|
65
|
+
if (!isObject(error)) {
|
|
66
|
+
const message = truncateSerializedErrorString(String(error));
|
|
67
|
+
return {
|
|
68
|
+
error: {
|
|
69
|
+
name: 'NonError',
|
|
70
|
+
message: message.trim() ? message : 'Empty string thrown'
|
|
71
|
+
},
|
|
72
|
+
hasMessage: Boolean(message.trim())
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const name = safelyReadProperty(error, 'name');
|
|
76
|
+
const serializedName = truncateSerializedErrorString('string' == typeof name && name ? name : 'Error');
|
|
77
|
+
const message = extractStringMessage(error);
|
|
78
|
+
const serialized = {
|
|
79
|
+
name: serializedName,
|
|
80
|
+
message: truncateSerializedErrorString(message ?? `${serializedName} without a message`)
|
|
81
|
+
};
|
|
82
|
+
const stack = getErrorStack(error);
|
|
83
|
+
if (stack) serialized.stack = truncateSerializedErrorString(stack);
|
|
84
|
+
const code = readBoundedDiagnostic(error, [
|
|
85
|
+
'code'
|
|
86
|
+
]);
|
|
87
|
+
const status = readBoundedDiagnostic(error, [
|
|
88
|
+
'status',
|
|
89
|
+
'statusCode'
|
|
90
|
+
]);
|
|
91
|
+
const requestId = readBoundedDiagnostic(error, [
|
|
92
|
+
'requestId',
|
|
93
|
+
'requestID'
|
|
94
|
+
]);
|
|
95
|
+
if (void 0 !== code) serialized.code = code;
|
|
96
|
+
if (void 0 !== status) serialized.status = status;
|
|
97
|
+
if (void 0 !== requestId) serialized.requestId = requestId;
|
|
98
|
+
return {
|
|
99
|
+
error: serialized,
|
|
100
|
+
hasMessage: void 0 !== message
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function serializeError(error) {
|
|
104
|
+
return serializeErrorValue(error).error;
|
|
105
|
+
}
|
|
106
|
+
export { getErrorMessage, getErrorStack, serializeError, truncateSerializedErrorString };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./base-tools.mjs";
|
|
2
|
+
export * from "./tool-defaults.mjs";
|
|
3
|
+
export * from "./agent-behavior-init-args.mjs";
|
|
4
|
+
export * from "./init-arg-utils.mjs";
|
|
5
|
+
export * from "./error-formatter.mjs";
|
|
6
|
+
export * from "./tool-generator.mjs";
|
|
7
|
+
export * from "./types.mjs";
|
|
8
|
+
export * from "./chrome-path.mjs";
|
|
9
|
+
export * from "./observation-record.mjs";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getKeyAliases, isRecord } from "../key-alias-utils.mjs";
|
|
2
|
+
function readAliasedValue(args, key) {
|
|
3
|
+
for (const alias of getKeyAliases(key))if (alias in args) return args[alias];
|
|
4
|
+
}
|
|
5
|
+
function readNamespacedArg(args, namespace, key) {
|
|
6
|
+
const namespacedArgs = readAliasedValue(args, namespace);
|
|
7
|
+
if (isRecord(namespacedArgs)) {
|
|
8
|
+
const nestedValue = readAliasedValue(namespacedArgs, key);
|
|
9
|
+
if (void 0 !== nestedValue) return nestedValue;
|
|
10
|
+
}
|
|
11
|
+
const dottedValue = readAliasedValue(args, `${namespace}.${key}`);
|
|
12
|
+
if (void 0 !== dottedValue) return dottedValue;
|
|
13
|
+
const directValue = readAliasedValue(args, key);
|
|
14
|
+
if (void 0 !== directValue) return directValue;
|
|
15
|
+
}
|
|
16
|
+
function extractNamespacedArgs(args, namespace, keys) {
|
|
17
|
+
const extracted = {};
|
|
18
|
+
for (const key of keys){
|
|
19
|
+
const value = readNamespacedArg(args, namespace, key);
|
|
20
|
+
if (void 0 !== value) extracted[key] = value;
|
|
21
|
+
}
|
|
22
|
+
return Object.keys(extracted).length > 0 ? extracted : void 0;
|
|
23
|
+
}
|
|
24
|
+
function sanitizeNamespacedArgs(args, namespace, keys) {
|
|
25
|
+
const excludedKeys = new Set(getKeyAliases(namespace));
|
|
26
|
+
for (const key of keys){
|
|
27
|
+
for (const alias of getKeyAliases(key))excludedKeys.add(alias);
|
|
28
|
+
for (const alias of getKeyAliases(`${namespace}.${key}`))excludedKeys.add(alias);
|
|
29
|
+
}
|
|
30
|
+
return Object.fromEntries(Object.entries(args).filter(([key])=>!excludedKeys.has(key)));
|
|
31
|
+
}
|
|
32
|
+
function createNamespacedInitArgSchema(namespace, shape) {
|
|
33
|
+
return Object.fromEntries(Object.entries(shape).map(([key, value])=>[
|
|
34
|
+
`${namespace}.${key}`,
|
|
35
|
+
value
|
|
36
|
+
]));
|
|
37
|
+
}
|
|
38
|
+
export { createNamespacedInitArgSchema, extractNamespacedArgs, sanitizeNamespacedArgs };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const observationArtifactAdapterSymbol = Symbol('midscene.observationArtifactAdapter');
|
|
2
|
+
function resolveObservationArtifactAdapter(agent) {
|
|
3
|
+
return agent[observationArtifactAdapterSymbol];
|
|
4
|
+
}
|
|
5
|
+
export { observationArtifactAdapterSymbol, resolveObservationArtifactAdapter };
|