browser-opt 1.0.1
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/browser-opt/index.d.ts +9 -0
- package/dist/browser-opt/index.d.ts.map +1 -0
- package/dist/browser-opt/index.js +7 -0
- package/dist/browser-opt/index.js.map +1 -0
- package/dist/browser-opt/runner/actions/index.d.ts +13 -0
- package/dist/browser-opt/runner/actions/index.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/index.js +44 -0
- package/dist/browser-opt/runner/actions/index.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/click-action.d.ts +10 -0
- package/dist/browser-opt/runner/actions/utils/click-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/click-action.js +17 -0
- package/dist/browser-opt/runner/actions/utils/click-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/date-action.d.ts +21 -0
- package/dist/browser-opt/runner/actions/utils/date-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/date-action.js +464 -0
- package/dist/browser-opt/runner/actions/utils/date-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/dom-action.d.ts +8 -0
- package/dist/browser-opt/runner/actions/utils/dom-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/dom-action.js +167 -0
- package/dist/browser-opt/runner/actions/utils/dom-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/fill-action.d.ts +10 -0
- package/dist/browser-opt/runner/actions/utils/fill-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/fill-action.js +20 -0
- package/dist/browser-opt/runner/actions/utils/fill-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/handoff-action.d.ts +10 -0
- package/dist/browser-opt/runner/actions/utils/handoff-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/handoff-action.js +6 -0
- package/dist/browser-opt/runner/actions/utils/handoff-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/open-action.d.ts +10 -0
- package/dist/browser-opt/runner/actions/utils/open-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/open-action.js +9 -0
- package/dist/browser-opt/runner/actions/utils/open-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/select-option-action.d.ts +17 -0
- package/dist/browser-opt/runner/actions/utils/select-option-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/select-option-action.js +532 -0
- package/dist/browser-opt/runner/actions/utils/select-option-action.js.map +1 -0
- package/dist/browser-opt/runner/actions/utils/upload-action.d.ts +7 -0
- package/dist/browser-opt/runner/actions/utils/upload-action.d.ts.map +1 -0
- package/dist/browser-opt/runner/actions/utils/upload-action.js +173 -0
- package/dist/browser-opt/runner/actions/utils/upload-action.js.map +1 -0
- package/dist/browser-opt/runner/evidence.d.ts +18 -0
- package/dist/browser-opt/runner/evidence.d.ts.map +1 -0
- package/dist/browser-opt/runner/evidence.js +116 -0
- package/dist/browser-opt/runner/evidence.js.map +1 -0
- package/dist/browser-opt/runner/handoff.d.ts +28 -0
- package/dist/browser-opt/runner/handoff.d.ts.map +1 -0
- package/dist/browser-opt/runner/handoff.js +132 -0
- package/dist/browser-opt/runner/handoff.js.map +1 -0
- package/dist/browser-opt/runner/index.d.ts +11 -0
- package/dist/browser-opt/runner/index.d.ts.map +1 -0
- package/dist/browser-opt/runner/index.js +244 -0
- package/dist/browser-opt/runner/index.js.map +1 -0
- package/dist/browser-opt/runner/step-executor.d.ts +5 -0
- package/dist/browser-opt/runner/step-executor.d.ts.map +1 -0
- package/dist/browser-opt/runner/step-executor.js +302 -0
- package/dist/browser-opt/runner/step-executor.js.map +1 -0
- package/dist/browser-opt/type.d.ts +120 -0
- package/dist/browser-opt/type.d.ts.map +1 -0
- package/dist/browser-opt/type.js +2 -0
- package/dist/browser-opt/type.js.map +1 -0
- package/dist/browser-opt/utils.d.ts +48 -0
- package/dist/browser-opt/utils.d.ts.map +1 -0
- package/dist/browser-opt/utils.js +885 -0
- package/dist/browser-opt/utils.js.map +1 -0
- package/dist/browser-opt/workflow/index.d.ts +7 -0
- package/dist/browser-opt/workflow/index.d.ts.map +1 -0
- package/dist/browser-opt/workflow/index.js +6 -0
- package/dist/browser-opt/workflow/index.js.map +1 -0
- package/dist/browser-opt/workflow/matcher.d.ts +12 -0
- package/dist/browser-opt/workflow/matcher.d.ts.map +1 -0
- package/dist/browser-opt/workflow/matcher.js +102 -0
- package/dist/browser-opt/workflow/matcher.js.map +1 -0
- package/dist/browser-opt/workflow/store.d.ts +15 -0
- package/dist/browser-opt/workflow/store.d.ts.map +1 -0
- package/dist/browser-opt/workflow/store.js +175 -0
- package/dist/browser-opt/workflow/store.js.map +1 -0
- package/dist/browser-opt/workflow/type.d.ts +43 -0
- package/dist/browser-opt/workflow/type.d.ts.map +1 -0
- package/dist/browser-opt/workflow/type.js +6 -0
- package/dist/browser-opt/workflow/type.js.map +1 -0
- package/dist/cli/browser-opt.d.ts +3 -0
- package/dist/cli/browser-opt.d.ts.map +1 -0
- package/dist/cli/browser-opt.js +11 -0
- package/dist/cli/browser-opt.js.map +1 -0
- package/dist/cli/commands/browser-opt.d.ts +2 -0
- package/dist/cli/commands/browser-opt.d.ts.map +1 -0
- package/dist/cli/commands/browser-opt.js +514 -0
- package/dist/cli/commands/browser-opt.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +10 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +35 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/utils/args.d.ts +17 -0
- package/dist/cli/utils/args.d.ts.map +1 -0
- package/dist/cli/utils/args.js +74 -0
- package/dist/cli/utils/args.js.map +1 -0
- package/dist/cli/utils/constants.d.ts +8 -0
- package/dist/cli/utils/constants.d.ts.map +1 -0
- package/dist/cli/utils/constants.js +18 -0
- package/dist/cli/utils/constants.js.map +1 -0
- package/dist/cli/utils/output.d.ts +7 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +45 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/package.json +35 -0
- package/skills/browser-opt/SKILL.md +249 -0
- package/skills/browser-opt/manifest.json +75 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一封装 CLI 参数解析与常用 flag 读取逻辑,避免各命令重复处理细节。
|
|
3
|
+
* 这里仅负责轻量解析,不引入命令语义,让命令文件保持聚焦在业务流程上。
|
|
4
|
+
*/
|
|
5
|
+
export function parseCliArgs(args) {
|
|
6
|
+
const positionals = [];
|
|
7
|
+
const flags = {};
|
|
8
|
+
for (let i = 0; i < args.length; i++) {
|
|
9
|
+
const token = args[i];
|
|
10
|
+
if (!token.startsWith('--')) {
|
|
11
|
+
positionals.push(token);
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const key = token.slice(2);
|
|
15
|
+
const next = args[i + 1];
|
|
16
|
+
if (next && !next.startsWith('--')) {
|
|
17
|
+
flags[key] = next;
|
|
18
|
+
i += 1;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
flags[key] = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { positionals, flags };
|
|
25
|
+
}
|
|
26
|
+
export function getStringFlag(flags, key) {
|
|
27
|
+
const value = flags[key];
|
|
28
|
+
return typeof value === 'string' ? value : undefined;
|
|
29
|
+
}
|
|
30
|
+
export function getBooleanFlag(flags, key) {
|
|
31
|
+
return flags[key] === true;
|
|
32
|
+
}
|
|
33
|
+
export function resolveProfile(flags) {
|
|
34
|
+
return getStringFlag(flags, 'profile');
|
|
35
|
+
}
|
|
36
|
+
export function resolveStatePath(flags) {
|
|
37
|
+
const flagState = getStringFlag(flags, 'state')?.trim();
|
|
38
|
+
if (flagState) {
|
|
39
|
+
return flagState;
|
|
40
|
+
}
|
|
41
|
+
const envState = process.env.AGENT_BROWSER_STATE?.trim();
|
|
42
|
+
return envState || undefined;
|
|
43
|
+
}
|
|
44
|
+
export function resolveReuseRunningBrowser(flags, statePath, defaultValue = false) {
|
|
45
|
+
if (statePath) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (getBooleanFlag(flags, 'clean-browser')) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (getBooleanFlag(flags, 'reuse-focused-browser')) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return defaultValue;
|
|
55
|
+
}
|
|
56
|
+
export function resolveLiveViewport(flags) {
|
|
57
|
+
if (getBooleanFlag(flags, 'no-live-viewport')) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (getBooleanFlag(flags, 'live-viewport')) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
export function parseCsv(value) {
|
|
66
|
+
if (!value) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
return value
|
|
70
|
+
.split(',')
|
|
71
|
+
.map((entry) => entry.trim())
|
|
72
|
+
.filter((entry) => entry.length > 0);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/cli/utils/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 存放 browser-opt CLI 复用的提示文案与常量,避免命令编排文件混入长文本。
|
|
3
|
+
* 当前只保留 browser-opt 自身会消费的内容,防止把 browser-e2e 边界带进来。
|
|
4
|
+
*/
|
|
5
|
+
export declare const LIVE_VIEWPORT_DASHBOARD_URL = "http://localhost:4848";
|
|
6
|
+
export declare const HANDOFF_DONE_ANSWERS: readonly ["done", "ok", "继续", "完成"];
|
|
7
|
+
export declare const BROWSER_OPT_USAGE = "\u4F7F\u7528\u65B9\u5F0F\uFF1A\n npx browser-opt <\u81EA\u7136\u8BED\u8A00\u6D41\u7A0B> [--profile <name>] [--state <path>] [--session <id>] [--no-live-viewport] [--output-dir <dir>] [--agent-chat]\n npx browser-opt setup [--with-deps] [--skip-skill] [--agent agents|codex] [--skills-dir <\u76EE\u5F55>]\n npx browser-opt save \"<\u540D\u79F0>\" --flow \"<\u5B8C\u6574\u6D41\u7A0B>\" [--workflow-dir <\u76EE\u5F55>] [--force]\n npx browser-opt run \"<\u67E5\u8BE2\u8BED\u53E5>\" [--workflow-dir <\u76EE\u5F55>]\n npx browser-opt run --workflow-id \"<ID>\" [--workflow-dir <\u76EE\u5F55>]\n npx browser-opt start --workflow-id \"<ID>\" [--workflow-dir <\u76EE\u5F55>] [--json]\n npx browser-opt status --run-id \"<ID>\" [--json]\n npx browser-opt resume --run-id \"<ID>\" [--json]\n npx browser-opt list [--workflow-dir <\u76EE\u5F55>] [--json]\n npx browser-opt match \"<\u67E5\u8BE2\u8BED\u53E5>\" [--workflow-dir <\u76EE\u5F55>] [--json]";
|
|
8
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,2BAA2B,0BAA0B,CAAC;AAEnE,eAAO,MAAM,oBAAoB,qCAAsC,CAAC;AAExE,eAAO,MAAM,iBAAiB,07BAUkC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 存放 browser-opt CLI 复用的提示文案与常量,避免命令编排文件混入长文本。
|
|
3
|
+
* 当前只保留 browser-opt 自身会消费的内容,防止把 browser-e2e 边界带进来。
|
|
4
|
+
*/
|
|
5
|
+
export const LIVE_VIEWPORT_DASHBOARD_URL = 'http://localhost:4848';
|
|
6
|
+
export const HANDOFF_DONE_ANSWERS = ['done', 'ok', '继续', '完成'];
|
|
7
|
+
export const BROWSER_OPT_USAGE = `使用方式:
|
|
8
|
+
npx browser-opt <自然语言流程> [--profile <name>] [--state <path>] [--session <id>] [--no-live-viewport] [--output-dir <dir>] [--agent-chat]
|
|
9
|
+
npx browser-opt setup [--with-deps] [--skip-skill] [--agent agents|codex] [--skills-dir <目录>]
|
|
10
|
+
npx browser-opt save "<名称>" --flow "<完整流程>" [--workflow-dir <目录>] [--force]
|
|
11
|
+
npx browser-opt run "<查询语句>" [--workflow-dir <目录>]
|
|
12
|
+
npx browser-opt run --workflow-id "<ID>" [--workflow-dir <目录>]
|
|
13
|
+
npx browser-opt start --workflow-id "<ID>" [--workflow-dir <目录>] [--json]
|
|
14
|
+
npx browser-opt status --run-id "<ID>" [--json]
|
|
15
|
+
npx browser-opt resume --run-id "<ID>" [--json]
|
|
16
|
+
npx browser-opt list [--workflow-dir <目录>] [--json]
|
|
17
|
+
npx browser-opt match "<查询语句>" [--workflow-dir <目录>] [--json]`;
|
|
18
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/cli/utils/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAExE,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;gEAU+B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一管理 browser-opt CLI 的结果输出,避免命令编排代码夹杂大量控制台细节。
|
|
3
|
+
* 该文件只保留 browser-opt 自己会用到的展示逻辑,不再耦合 browser-e2e 文案。
|
|
4
|
+
*/
|
|
5
|
+
import type { BrowserOptRunResult } from '../../browser-opt/type.js';
|
|
6
|
+
export declare function printBrowserOptResult(result: BrowserOptRunResult): void;
|
|
7
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGrE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CA8CvE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { collectFailedBrowserOptSteps, formatBrowserOptStepStatus } from '../../browser-opt/utils.js';
|
|
2
|
+
export function printBrowserOptResult(result) {
|
|
3
|
+
if (result.passed) {
|
|
4
|
+
console.log('执行成功');
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
const { report } = result;
|
|
8
|
+
console.log(`Status: ${report.status}`);
|
|
9
|
+
if (report.handoffTriggered) {
|
|
10
|
+
console.log('Handoff: 已触发,请在浏览器中完成登录后输入 done 继续。');
|
|
11
|
+
}
|
|
12
|
+
console.log(`Report JSON: ${report.reportJsonPath}`);
|
|
13
|
+
console.log(`Report Markdown: ${report.reportMarkdownPath}`);
|
|
14
|
+
console.log(`Log: ${report.logPath}`);
|
|
15
|
+
const failedSteps = collectFailedBrowserOptSteps(report);
|
|
16
|
+
console.log('Failed steps:');
|
|
17
|
+
if (failedSteps.length === 0) {
|
|
18
|
+
console.log(' - n/a');
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
for (const step of failedSteps) {
|
|
22
|
+
console.log(` - ${step.index}. ${step.instruction}`);
|
|
23
|
+
console.log(` Reason: ${step.error ?? step.verification ?? '未知原因'}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
console.log('Evidence screenshots:');
|
|
27
|
+
for (const screenshot of report.screenshots) {
|
|
28
|
+
console.log(` - ${screenshot}`);
|
|
29
|
+
}
|
|
30
|
+
console.log('Detailed log:');
|
|
31
|
+
for (const log of report.logs) {
|
|
32
|
+
console.log(` ${log}`);
|
|
33
|
+
}
|
|
34
|
+
for (const step of report.steps) {
|
|
35
|
+
const mark = formatBrowserOptStepStatus(step);
|
|
36
|
+
console.log(`${mark} ${step.index}. ${step.instruction}`);
|
|
37
|
+
if (step.handoffTriggered && step.verification) {
|
|
38
|
+
console.log(` Handoff: ${step.verification}`);
|
|
39
|
+
}
|
|
40
|
+
if (step.error) {
|
|
41
|
+
console.log(` Error: ${step.error}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAEtG,MAAM,UAAU,qBAAqB,CAAC,MAA2B;IAC/D,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAEtC,MAAM,WAAW,GAAG,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,OAAO,UAAU,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1D,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "browser-opt",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "带证据报告的自然语言浏览器工作流 CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/browser-opt/index.js",
|
|
7
|
+
"types": "dist/browser-opt/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/browser-opt/index.js",
|
|
11
|
+
"types": "./dist/browser-opt/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"browser-opt": "dist/cli/browser-opt.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"skills/browser-opt"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.json",
|
|
23
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=24.0.0"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@browser-automated/browser-core": "1.0.0",
|
|
33
|
+
"agent-browser": "^0.33.1"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browser-opt
|
|
3
|
+
description: Execute natural-language browser flows with agent-browser and produce simplified PASS/FAIL results.
|
|
4
|
+
summary: Run deterministic browser execution loops with screenshots, JSON snapshots, retries, and concise success output.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# browser-opt skill
|
|
8
|
+
|
|
9
|
+
This skill is the deterministic browser execution entrypoint. It is intentionally separate from `browser-e2e`: `browser-opt` runs the flow now and reports evidence; it does not match generated tests or create Playwright code.
|
|
10
|
+
|
|
11
|
+
By default, the calling AI is responsible for understanding the page from `snapshot --json`; `agent-browser` only executes deterministic commands such as `open`, `fill @ref`, `click @ref`, screenshots, and waits. Do not use `agent-browser chat` unless the user explicitly asks for the legacy chat mode or passes `--agent-chat`.
|
|
12
|
+
|
|
13
|
+
Natural-language steps that explicitly ask to open developer tools are mapped to
|
|
14
|
+
CDP's experimental `Target.openDevTools` command. This opens native DevTools for
|
|
15
|
+
the active target in the same Chrome window; do not use `agent-browser inspect`,
|
|
16
|
+
which opens a separate DevTools frontend URL. If the current Chrome version does
|
|
17
|
+
not support `Target.openDevTools`, report the failure instead of falling back to
|
|
18
|
+
the separate frontend. Supported expressions include `打开开发者工具`,
|
|
19
|
+
`启动 DevTools`, `调起 Chrome DevTools`, and `inspect current page`:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
/browser-opt 测试 https://example.com 的页面调试流程。
|
|
23
|
+
|
|
24
|
+
目标:
|
|
25
|
+
1. 打开开发者工具。
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Image upload examples
|
|
29
|
+
|
|
30
|
+
For test environments, describe upload steps as automatic URL uploads. `browser-opt` downloads the remote image into the run evidence directory and calls `agent-browser upload` with the local file path:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
/browser-opt 测试 https://example.com/live/create 的直播间创建流程。
|
|
34
|
+
|
|
35
|
+
目标:
|
|
36
|
+
1. 打开页面。
|
|
37
|
+
2. 在“直播间名称”输入“自动化测试直播间”。
|
|
38
|
+
3. 自动上传“直播间分享封面”,图片来源 URL 为“https://stantic.ifengqun.com/front/fq-ecmiddle-sys/upload/82243689cae75e27b3867a5cbdd4292b.png”。
|
|
39
|
+
4. 自动上传“直播间封面”,图片来源 URL 为“https://stantic.ifengqun.com/front/fq-ecmiddle-sys/upload/82243689cae75e27b3867a5cbdd4292b.png”。
|
|
40
|
+
5. 验证页面显示封面预览或上传成功状态。
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For production environments, describe upload steps as manual handoff so the operator can choose real local images through the system file picker:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
/browser-opt 操作 https://example.com/live/create 的直播间创建流程。
|
|
47
|
+
|
|
48
|
+
目标:
|
|
49
|
+
1. 打开页面。
|
|
50
|
+
2. 在“直播间名称”输入“正式直播间名称”。
|
|
51
|
+
3. handoff 给操作人员:请手动选择“直播间分享封面”的本地真实图片,并在裁剪/确认完成后恢复自动化。
|
|
52
|
+
4. handoff 给操作人员:请手动选择“直播间封面”的本地真实图片,并在裁剪/确认完成后恢复自动化。
|
|
53
|
+
5. 验证页面显示封面预览或上传成功状态。
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Required agent-browser practice
|
|
57
|
+
|
|
58
|
+
Every execution must follow these rules:
|
|
59
|
+
|
|
60
|
+
- Always open the actual system Chrome browser for the run. Do not open or operate inside the agent tool's built-in browser, including the Copilot/Codex in-app browser or any agent-browser dashboard/preview window.
|
|
61
|
+
- Strictly run an `open -> snapshot --json -> deterministic act -> re-snapshot` loop.
|
|
62
|
+
- Take a screenshot for every step.
|
|
63
|
+
- Use text matching or element existence checks for verification points.
|
|
64
|
+
- Retry with a fresh snapshot when an action fails or an element reference is stale.
|
|
65
|
+
- Use `--json` output when parsing elements.
|
|
66
|
+
- After every step, reason about the current page state and the next action.
|
|
67
|
+
- If a reference becomes invalid, take a fresh snapshot before retrying.
|
|
68
|
+
- Prefer deterministic commands and element refs over natural-language `chat`.
|
|
69
|
+
- Final report must include `PASS` or `FAIL`, evidence screenshot paths, and detailed logs.
|
|
70
|
+
|
|
71
|
+
## Interactive handoff execution
|
|
72
|
+
|
|
73
|
+
For saved workflows, start the browser run as a detached task and keep the returned stable `runId`. Do not keep an `exec_command` or PTY session id as the recovery handle; Codex may discard that process handle when the handoff response ends the current turn.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx --yes browser-opt start --workflow-id "<matched.id>" --json
|
|
77
|
+
npx --yes browser-opt status --run-id "<runId>" --json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Poll `status` until it returns `PASS`, `FAIL`, or `HANDOFF`. When it returns `HANDOFF`, ask the user to finish the manual action and end the current turn normally. After the user replies `done`, restore the original runner and browser with:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx --yes browser-opt resume --run-id "<runId>" --json
|
|
84
|
+
npx --yes browser-opt status --run-id "<runId>" --json
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The detached task still executes `browser-opt run` exactly once. `status` is read-only and `resume` only sends a one-time signal to that original process. Never start a second `run` or `start` command to simulate resume.
|
|
88
|
+
|
|
89
|
+
## Saved workflows
|
|
90
|
+
|
|
91
|
+
Reusable flows are stored as JSON files under the calling project's
|
|
92
|
+
`.browser-opt/workflows/` directory by default. Resolve relative paths from the
|
|
93
|
+
calling project's current working directory, not from this skill or package directory.
|
|
94
|
+
|
|
95
|
+
Install the published CLI and this Skill with `npx --yes browser-opt setup`.
|
|
96
|
+
By default it installs to the shared Agent Skills directory, similar to
|
|
97
|
+
`npx skills add`. Use `--agent codex` for the Codex-specific skills directory,
|
|
98
|
+
or `--skills-dir <dir>` for another agent root.
|
|
99
|
+
Use this command prefix for every `browser-opt` invocation:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx --yes browser-opt
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Only use `browser-opt ...` when `command -v browser-opt` succeeds in the same
|
|
106
|
+
execution environment; otherwise use `npx --yes browser-opt ...`.
|
|
107
|
+
|
|
108
|
+
Save a complete flow without executing it:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npx --yes browser-opt save "创建安选公开直播流程" --flow "<full natural language flow>"
|
|
112
|
+
npx --yes browser-opt save "创建安选公开直播流程" --flow "<full natural language flow>" --workflow-dir ./custom/workflows
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Saving an existing name fails by default. Only pass `--force` when the user
|
|
116
|
+
explicitly wants to replace it.
|
|
117
|
+
|
|
118
|
+
Saved workflow files are structured JSON, not a single `flow` string. The
|
|
119
|
+
persisted schema uses `target.url` as the page entrypoint plus a `steps` string
|
|
120
|
+
array for business actions after the page is opened. When `target.url` exists,
|
|
121
|
+
do not include a first step such as "打开页面":
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"id": "创建安选公开直播流程",
|
|
126
|
+
"name": "创建安选公开直播流程",
|
|
127
|
+
"target": {
|
|
128
|
+
"url": "https://example.com/live/create"
|
|
129
|
+
},
|
|
130
|
+
"steps": [
|
|
131
|
+
"在“直播间名称”输入“自动化测试直播间”。",
|
|
132
|
+
"验证页面包含“创建成功”。"
|
|
133
|
+
],
|
|
134
|
+
"createdAt": "2026-07-28T08:00:00.000Z",
|
|
135
|
+
"updatedAt": "2026-07-28T08:00:00.000Z"
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
When `/browser-opt` is followed by a short request without a URL, such as:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
/browser-opt 执行创建安选公开直播流程
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Do not treat it as a new one-shot flow. First run:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx --yes browser-opt match "<short request>" --json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Handle the JSON result as follows:
|
|
152
|
+
|
|
153
|
+
- `matched`: run `npx --yes browser-opt start --workflow-id "<matched.id>" --json`, retain its `runId`, and follow the interactive handoff execution protocol above.
|
|
154
|
+
- `ambiguous`: do not rely on the CLI's human-readable stdout as the user-facing
|
|
155
|
+
choice list, and do not ask through a modal/input tool that may render Markdown
|
|
156
|
+
as plain text. Parse `match --json`, then ask in a normal assistant message.
|
|
157
|
+
Show the returned candidates, at most three, numbered from 1. Render each
|
|
158
|
+
candidate name itself as a Markdown file link using `filePath`, such as
|
|
159
|
+
`[创建安选公开直播流程](</absolute/path/创建安选公开直播流程.json>)`. Do not show a
|
|
160
|
+
bare `file://` URL. Ask the user to reply with the number (for example `1`,
|
|
161
|
+
`2`, or `3`), even when there is only one weakly similar candidate. Do not
|
|
162
|
+
open a browser before the choice. Then map the selected number back to the
|
|
163
|
+
candidate ID and run it. In GitHub Copilot Chat, local Markdown file links may
|
|
164
|
+
render as plain text; include `displayPath` in backticks after the link so the
|
|
165
|
+
path remains visible and can be opened through VS Code's file detection.
|
|
166
|
+
- `not-found`: tell the user no saved workflow matched and show the returned
|
|
167
|
+
available workflow names as Markdown file links using `filePath` when present.
|
|
168
|
+
Ask for a more specific request or a full flow with URL.
|
|
169
|
+
- Warnings describe invalid workflow files that were skipped. Report them without
|
|
170
|
+
blocking valid candidates.
|
|
171
|
+
|
|
172
|
+
Use `--workflow-dir` consistently on both `match` and `run` when the user selects
|
|
173
|
+
a custom directory. Use `npx --yes browser-opt list --json` when
|
|
174
|
+
the user asks to see all saved workflows.
|
|
175
|
+
|
|
176
|
+
Example ambiguous response format:
|
|
177
|
+
|
|
178
|
+
```markdown
|
|
179
|
+
匹配结果是 `ambiguous`,请回复要执行的流程编号:
|
|
180
|
+
|
|
181
|
+
1. [创建安选公开直播(测试环境)](</Users/lee/project/.browser-opt/workflows/创建安选公开直播(测试环境).json>)
|
|
182
|
+
`.browser-opt/workflows/创建安选公开直播(测试环境).json`
|
|
183
|
+
2. [创建安选私域直播](</Users/lee/project/.browser-opt/workflows/创建安选私域直播.json>)
|
|
184
|
+
`.browser-opt/workflows/创建安选私域直播.json`
|
|
185
|
+
|
|
186
|
+
请回复数字,例如 `1`。
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Trigger
|
|
190
|
+
|
|
191
|
+
Use `/browser-opt` followed by either a full natural-language flow or a saved
|
|
192
|
+
workflow request. A full flow includes its target URL:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
/browser-opt 测试 https://example.com 的搜索功能。
|
|
196
|
+
|
|
197
|
+
目标:
|
|
198
|
+
1. 打开首页。
|
|
199
|
+
2. 在搜索框输入 "agent-browser"。
|
|
200
|
+
3. 点击搜索按钮。
|
|
201
|
+
4. 验证搜索结果页面是否包含至少 3 个结果项。
|
|
202
|
+
5. 点击第一个结果,验证跳转正确。
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Translate that into:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npx --yes browser-opt "<full natural language flow>"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Optional runtime flags:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
npx --yes browser-opt "<flow>" --profile Default
|
|
215
|
+
npx --yes browser-opt "<flow>" --state ./.browser-opt/states/browser-opt-default.json
|
|
216
|
+
npx --yes browser-opt "<flow>" --no-live-viewport
|
|
217
|
+
npx --yes browser-opt "<flow>" --output-dir ./.browser-opt/artifacts
|
|
218
|
+
npx --yes browser-opt "<flow>" --agent-chat
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Auth state reuse policy:
|
|
222
|
+
|
|
223
|
+
- `browser-opt` first checks its saved auth state under `.browser-opt/states/`.
|
|
224
|
+
- If a default state file exists, it loads that state first, so only cookies/storage are reused and prior Chrome tabs are not restored.
|
|
225
|
+
- If the default state opens on a login screen or later redirects there, close the state window and replace it once with the selected Chrome profile before entering handoff. Keep that profile window and the original `browser-opt` runner alive for resume so the operator can use Chrome's password manager.
|
|
226
|
+
- Saved workflows keep the original runner alive as a detached task and use `runId` for handoff recovery across Codex turns; an `exec_command` session id is never a durable recovery handle.
|
|
227
|
+
- Programmatic runs use the same one-time profile fallback when the default state is invalid.
|
|
228
|
+
- If no default state file exists, the single main agent opens the target directly with `--profile Default` and saves state from that same window. Do not create a separate profile importer.
|
|
229
|
+
- Pass `--profile <name>` to choose a different Chrome profile for first import and default-state fallback.
|
|
230
|
+
- Pass `--state <path>` to use a custom state file without automatic profile fallback.
|
|
231
|
+
- Do not rely on focused-browser reuse for login import: ordinary Chrome is usually not CDP-accessible, and auto-connect can attach to the wrong temporary browser.
|
|
232
|
+
|
|
233
|
+
It shows and keeps the actual system Chrome browser by default so the user can watch the operation and inspect the final page state. This must be a real Chrome window, not the agent tool's built-in browser such as the Copilot/Codex in-app browser, and it must not open the agent-browser dashboard at `http://localhost:4848`. Use `--no-live-viewport` only when the user explicitly wants headless execution. `--agent-chat` is a legacy compatibility mode. It may require `AI_GATEWAY_API_KEY`; avoid it when the caller can inspect snapshots and produce deterministic actions.
|
|
234
|
+
|
|
235
|
+
## Output
|
|
236
|
+
|
|
237
|
+
The CLI writes an evidence directory under `.browser-opt/artifacts/` unless `--output-dir` is provided.
|
|
238
|
+
|
|
239
|
+
Expected artifacts:
|
|
240
|
+
|
|
241
|
+
- `report.json` for machine parsing.
|
|
242
|
+
- `report.md` for human review.
|
|
243
|
+
- `00-open.png`, `01-before.png`, `01-after.png`, and later step screenshots.
|
|
244
|
+
- `*.snapshot.json` files captured through `agent-browser snapshot -i --json`.
|
|
245
|
+
|
|
246
|
+
The assistant response must be concise:
|
|
247
|
+
|
|
248
|
+
- If the run succeeds, reply only with `执行成功`.
|
|
249
|
+
- If the run fails, summarize the failure status, report paths, screenshot paths, and failing step.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "browser-opt",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Run immediate or project-saved natural-language browser workflows with simplified PASS/FAIL results",
|
|
5
|
+
"triggers": [
|
|
6
|
+
"browser-opt",
|
|
7
|
+
"natural language browser flow",
|
|
8
|
+
"execute browser flow",
|
|
9
|
+
"自然语言执行浏览器流程",
|
|
10
|
+
"执行已保存的浏览器流程",
|
|
11
|
+
"运行 workflow"
|
|
12
|
+
],
|
|
13
|
+
"inputs": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"flow": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Full natural-language browser flow including a URL and expected steps"
|
|
19
|
+
},
|
|
20
|
+
"query": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Short request used to match a saved workflow in the calling project"
|
|
23
|
+
},
|
|
24
|
+
"workflowDir": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Optional workflow directory, default .browser-opt/workflows under the calling project"
|
|
27
|
+
},
|
|
28
|
+
"profile": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Chrome profile name or path. Use state for login-only reuse; profile keeps full Chrome profile behavior."
|
|
31
|
+
},
|
|
32
|
+
"state": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Path to an agent-browser state file. Preferred for reusing login state without restoring tabs or Chrome recovery UI."
|
|
35
|
+
},
|
|
36
|
+
"liveViewport": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"description": "Whether to show the actual system Chrome browser, default true; never use the agent tool's built-in browser or the agent-browser dashboard"
|
|
39
|
+
},
|
|
40
|
+
"outputDir": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Optional directory for evidence reports"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"outputs": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": {
|
|
49
|
+
"status": {
|
|
50
|
+
"enum": [
|
|
51
|
+
"PASS",
|
|
52
|
+
"FAIL"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"reportJsonPath": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"reportMarkdownPath": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
},
|
|
61
|
+
"screenshotPaths": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "string"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"logPaths": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"items": {
|
|
70
|
+
"type": "string"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|