@qing3a/flow-rpa-app 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ import { type RunConfig } from './config.js';
2
+ /**
3
+ * CLI(移植 Rust `main.rs`,node:util parseArgs)。
4
+ * 参数兼容:--flows / --data / --mock / --port / --edge / --platform-url / --platform-token /
5
+ * list / validate <flow.json>。
6
+ *
7
+ * D-N3 缺省目录语义(M11a 定案):
8
+ * - 显式 --flows/--data → 用传入值
9
+ * - `FLOW_RPA_HOME` 环境变量 → 该目录下 flows/、data/
10
+ * - 本地开发(cwd 下有 flows/ 目录)→ 相对 cwd 的 flows/、data/(仓库根语义不变)
11
+ * - 全局安装(cwd 无 flows/)→ `~/.flow-rpa/flows`、`~/.flow-rpa/data`
12
+ */
13
+ export interface CliOptions {
14
+ flowsDir: string;
15
+ dataDir: string;
16
+ mock: boolean;
17
+ cdpPort?: number;
18
+ edgePath?: string;
19
+ platformUrl?: string;
20
+ platformToken?: string;
21
+ /** M11d:--http 常驻模式 */
22
+ http: boolean;
23
+ /** --http-port(默认 3081) */
24
+ httpPort?: number;
25
+ /** --http-token(可选认证) */
26
+ httpToken?: string;
27
+ /** 位置参数(list / validate <path> / install-skill <dir>) */
28
+ positionals?: string[];
29
+ }
30
+ /** D-N3:缺省目录(本地开发 → 仓库根;全局 → ~/.flow-rpa) */
31
+ export declare function defaultDirs(): {
32
+ flowsDir: string;
33
+ dataDir: string;
34
+ };
35
+ export declare function parseCli(argv: string[]): CliOptions;
36
+ /** 从 CLI 选项构造 RunConfig(含环境变量兜底) */
37
+ export declare function configFromCli(opts: CliOptions): RunConfig;
38
+ /**
39
+ * M11c D-K2:install-skill —— 拷贝引擎级 skill 到 Agent 平台的 skills 目录。
40
+ * skill 内容来自包内 skill/flow-rpa-engine.md(构建时从 docs/SKILL-ENGINE.md 复制,唯一真源)。
41
+ * D-K3:拷贝时在文件头写引擎版本(v<version>),供 Agent 侧判断是否需要更新。
42
+ * 幂等:直接覆盖(重复安装安全)。
43
+ */
44
+ export declare function installSkill(targetDir: string): void;
45
+ /** CLI 子命令:list / validate / install-skill;返回 true 表示已处理(退出) */
46
+ export declare function runCliCommand(opts: CliOptions & {
47
+ positionals?: string[];
48
+ }): boolean;
package/dist/cli.js ADDED
@@ -0,0 +1,145 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { readFileSync, existsSync, mkdirSync, copyFileSync, writeFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join, dirname } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { parseFlow } from '@qing3a/flow-rpa-engine/src/validate.js';
7
+ import { FlowRegistry } from './registry.js';
8
+ import { defaultRunConfig } from './config.js';
9
+ /** D-N3:缺省目录(本地开发 → 仓库根;全局 → ~/.flow-rpa) */
10
+ export function defaultDirs() {
11
+ const home = process.env.FLOW_RPA_HOME;
12
+ if (home && home.length > 0) {
13
+ return { flowsDir: join(home, 'flows'), dataDir: join(home, 'data') };
14
+ }
15
+ if (existsSync(join(process.cwd(), 'flows'))) {
16
+ // 本地开发:仓库根语义不变
17
+ return { flowsDir: 'flows', dataDir: 'data' };
18
+ }
19
+ // 全局安装:用户目录 ~/.flow-rpa
20
+ const base = join(homedir(), '.flow-rpa');
21
+ return { flowsDir: join(base, 'flows'), dataDir: join(base, 'data') };
22
+ }
23
+ export function parseCli(argv) {
24
+ const { values, positionals } = parseArgs({
25
+ args: argv,
26
+ options: {
27
+ flows: { type: 'string' },
28
+ data: { type: 'string' },
29
+ mock: { type: 'boolean', default: false },
30
+ port: { type: 'string' },
31
+ edge: { type: 'string' },
32
+ 'platform-url': { type: 'string' },
33
+ 'platform-token': { type: 'string' },
34
+ http: { type: 'boolean', default: false },
35
+ 'http-port': { type: 'string' },
36
+ 'http-token': { type: 'string' },
37
+ },
38
+ allowPositionals: true,
39
+ strict: false,
40
+ });
41
+ const str = (v) => (typeof v === 'string' ? v : undefined);
42
+ const d = defaultDirs();
43
+ return {
44
+ flowsDir: str(values.flows) ?? d.flowsDir,
45
+ dataDir: str(values.data) ?? d.dataDir,
46
+ mock: values.mock === true,
47
+ cdpPort: str(values.port) !== undefined ? Number(str(values.port)) : undefined,
48
+ edgePath: str(values.edge),
49
+ platformUrl: str(values['platform-url']),
50
+ platformToken: str(values['platform-token']),
51
+ http: values.http === true,
52
+ httpPort: str(values['http-port']) !== undefined ? Number(str(values['http-port'])) : undefined,
53
+ httpToken: str(values['http-token']),
54
+ positionals,
55
+ };
56
+ }
57
+ /** 从 CLI 选项构造 RunConfig(含环境变量兜底) */
58
+ export function configFromCli(opts) {
59
+ const config = defaultRunConfig(opts.dataDir, opts.mock);
60
+ if (opts.cdpPort !== undefined && !Number.isNaN(opts.cdpPort))
61
+ config.cdpPort = opts.cdpPort;
62
+ if (opts.edgePath !== undefined && opts.edgePath.length > 0)
63
+ config.edgePath = opts.edgePath;
64
+ config.platformUrl = opts.platformUrl ?? process.env.FLOW_PLATFORM_URL ?? '';
65
+ config.platformToken = opts.platformToken ?? process.env.FLOW_PLATFORM_TOKEN ?? '';
66
+ return config;
67
+ }
68
+ /**
69
+ * M11c D-K2:install-skill —— 拷贝引擎级 skill 到 Agent 平台的 skills 目录。
70
+ * skill 内容来自包内 skill/flow-rpa-engine.md(构建时从 docs/SKILL-ENGINE.md 复制,唯一真源)。
71
+ * D-K3:拷贝时在文件头写引擎版本(v<version>),供 Agent 侧判断是否需要更新。
72
+ * 幂等:直接覆盖(重复安装安全)。
73
+ */
74
+ export function installSkill(targetDir) {
75
+ // 定位包内 skill 文件(构建后 dist/cli.js → 包内 skill/ 在上一级)
76
+ const here = dirname(fileURLToPath(import.meta.url));
77
+ const pkgRoot = dirname(here); // dist/ → 包根
78
+ const skillSrc = join(pkgRoot, 'skill', 'flow-rpa-engine.md');
79
+ if (!existsSync(skillSrc)) {
80
+ console.error(`✗ skill 文件不存在: ${skillSrc}(先跑 pnpm build 生成)`);
81
+ process.exit(1);
82
+ }
83
+ // 引擎版本(包版本)
84
+ const pkgJson = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf8'));
85
+ const version = pkgJson.version ?? '0.0.0';
86
+ // 文件头加版本标注(D-K3:v<version> 供 Agent 判断更新)
87
+ const body = readFileSync(skillSrc, 'utf8');
88
+ const header = `<!-- flow-rpa-engine skill v${version} · 由 flow-app install-skill 安装 · 覆盖安装幂等 -->\n`;
89
+ // 幂等:已含本版本头部则跳过写头(覆盖内容)
90
+ const final = body.startsWith('<!-- flow-rpa-engine skill v') ? body.replace(/^<!-- [^\n]*\n/, header) : header + body;
91
+ mkdirSync(targetDir, { recursive: true });
92
+ const dest = join(targetDir, 'flow-rpa-engine.md');
93
+ writeFileSync(dest, final, 'utf8');
94
+ console.log(`✓ 已安装 skill: ${dest}`);
95
+ console.log(` 引擎版本: v${version}`);
96
+ console.log(' 说明:把引擎级 skill 放到 Agent 平台的 skills 目录(WorkBuddy ~/.agents/skills/、Claude ~/.claude/skills/),');
97
+ console.log(' 或引用该文件路径。skill 内容真源是 docs/SKILL-ENGINE.md,随包版本更新。');
98
+ }
99
+ /** CLI 子命令:list / validate / install-skill;返回 true 表示已处理(退出) */
100
+ export function runCliCommand(opts) {
101
+ const cmd = opts.positionals?.[0];
102
+ if (cmd === 'list') {
103
+ const reg = new FlowRegistry(opts.flowsDir);
104
+ const flows = reg.list();
105
+ if (flows.length === 0) {
106
+ console.log('没有可用的流程(flows/ 目录下无 flow.json)');
107
+ }
108
+ else {
109
+ for (const f of flows) {
110
+ console.log(`- ${f.id}(v${f.version}): ${f.name} [${f.path}]`);
111
+ }
112
+ }
113
+ return true;
114
+ }
115
+ if (cmd === 'install-skill') {
116
+ const target = opts.positionals?.[1];
117
+ if (!target) {
118
+ console.log('用法: flow-app install-skill <target-dir>');
119
+ console.log(' 把引擎级 skill(flow-rpa-engine.md)拷贝到 Agent 平台的 skills 目录。');
120
+ console.log(' 常见位置:WorkBuddy ~/.agents/skills/、Claude ~/.claude/skills/');
121
+ process.exit(2);
122
+ }
123
+ installSkill(target);
124
+ return true;
125
+ }
126
+ if (cmd === 'validate') {
127
+ const path = opts.positionals?.[1];
128
+ if (!path) {
129
+ console.log('用法: flow-app validate <flow.json>');
130
+ process.exit(2);
131
+ }
132
+ try {
133
+ const raw = readFileSync(path, 'utf8');
134
+ const flow = parseFlow(raw);
135
+ console.log(`✓ 流程合法: ${flow.id}(v${flow.version}): ${flow.name}`);
136
+ }
137
+ catch (e) {
138
+ console.log(`✗ 流程不合法: ${e instanceof Error ? e.message : String(e)}`);
139
+ process.exit(1);
140
+ }
141
+ return true;
142
+ }
143
+ return false;
144
+ }
145
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { type SimProfile } from '@qing3a/flow-rpa-engine/src/simprofile.js';
2
+ /**
3
+ * 运行配置(浏览器/驱动选择;移植 Rust `server.rs` RunConfig)。
4
+ */
5
+ export interface RunConfig {
6
+ /** CDP 调试端口 */
7
+ cdpPort: number;
8
+ /** Edge 可执行文件路径(空 = 不自动拉起浏览器) */
9
+ edgePath: string;
10
+ /** 独立浏览器 profile 目录 */
11
+ userDataDir: string;
12
+ /** true = 用 mock 页面驱动(调试/无浏览器环境) */
13
+ mock: boolean;
14
+ /** 拟人参数(机器差异化,启动时加载) */
15
+ simProfile: SimProfile;
16
+ /** md-forge 平台地址(pkg_update 用;空 = 未配置) */
17
+ platformUrl: string;
18
+ /** md-forge 共享令牌 */
19
+ platformToken: string;
20
+ }
21
+ /** 探测本机 Edge 可执行文件(Windows 常见安装路径) */
22
+ export declare function defaultEdgePath(): string;
23
+ /** 默认配置:真实浏览器驱动,profile 与 sim 参数在 data 目录 */
24
+ export declare function defaultRunConfig(dataDir: string, mock: boolean): RunConfig;
package/dist/config.js ADDED
@@ -0,0 +1,28 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { CDP_PORT } from '@qing3a/flow-rpa-engine/src/cdp/client.js';
4
+ import { defaultProfileFile, loadSimProfile } from '@qing3a/flow-rpa-engine/src/simprofile.js';
5
+ /** 探测本机 Edge 可执行文件(Windows 常见安装路径) */
6
+ export function defaultEdgePath() {
7
+ for (const p of [
8
+ 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
9
+ 'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe',
10
+ ]) {
11
+ if (existsSync(p))
12
+ return p;
13
+ }
14
+ return '';
15
+ }
16
+ /** 默认配置:真实浏览器驱动,profile 与 sim 参数在 data 目录 */
17
+ export function defaultRunConfig(dataDir, mock) {
18
+ return {
19
+ cdpPort: CDP_PORT,
20
+ edgePath: defaultEdgePath(),
21
+ userDataDir: join(dataDir, 'edge-profile'),
22
+ mock,
23
+ simProfile: loadSimProfile(defaultProfileFile(dataDir)).profile,
24
+ platformUrl: '',
25
+ platformToken: '',
26
+ };
27
+ }
28
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,2CAA2C,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAmB,MAAM,2CAA2C,CAAA;AAuB/G,sCAAsC;AACtC,MAAM,UAAU,eAAe;IAC7B,KAAK,MAAM,CAAC,IAAI;QACd,mEAAmE;QACnE,6DAA6D;KAC9D,EAAE,CAAC;QACF,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;IAC7B,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,IAAa;IAC7D,OAAO;QACL,OAAO,EAAE,QAAQ;QACjB,QAAQ,EAAE,eAAe,EAAE;QAC3B,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC;QAC1C,IAAI;QACJ,UAAU,EAAE,cAAc,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QAC/D,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,EAAE;KAClB,CAAA;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * M1 骨架占位:验证 workspace 跨包引用链路(Rust → TypeScript 迁移脚手架)。
3
+ * 正式模块(server/registry/runner/cli)在 M9 按 MIGRATION-NODE 模块映射落地。
4
+ */
5
+ export declare function appHello(): string;
package/dist/hello.js ADDED
@@ -0,0 +1,9 @@
1
+ import { engineHello } from '@qing3a/flow-rpa-engine/src/hello.js';
2
+ /**
3
+ * M1 骨架占位:验证 workspace 跨包引用链路(Rust → TypeScript 迁移脚手架)。
4
+ * 正式模块(server/registry/runner/cli)在 M9 按 MIGRATION-NODE 模块映射落地。
5
+ */
6
+ export function appHello() {
7
+ return `app hello: ${engineHello()}`;
8
+ }
9
+ //# sourceMappingURL=hello.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hello.js","sourceRoot":"","sources":["../src/hello.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAA;AAElE;;;GAGG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,cAAc,WAAW,EAAE,EAAE,CAAA;AACtC,CAAC"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import type { RunConfig } from './config.js';
2
+ /**
3
+ * M11d D-H1/D-H2/D-H3:--http 常驻模式(StreamableHTTPServerTransport)。
4
+ * - POST /mcp:JSON-RPC(streamable HTTP 主端点)
5
+ * - GET /mcp:SSE 流(可选,SDK 支持时提供)
6
+ * - GET /health:健康检查(只读状态页复用,M11e)
7
+ * - GET /status.json:自描述状态 JSON(D-S1;与状态页同一数据源,只读)
8
+ * - 与 stdio 共用 data/.lock(D-R2 互斥:两个模式不能同时跑)
9
+ * - 默认端口 3081(--http-port 覆盖);--http-token 可选开启环回认证
10
+ */
11
+ export declare const DEFAULT_HTTP_PORT = 3081;
12
+ /** M11d 启动选项 */
13
+ export interface HttpServeOptions {
14
+ flowsDir: string;
15
+ dataDir: string;
16
+ config: RunConfig;
17
+ /** HTTP 端口(默认 3081;0 = 随机端口,测试用) */
18
+ port?: number;
19
+ /** 可选认证 token(空 = 本地环回不加认证) */
20
+ token?: string;
21
+ /** 测试用:监听成功后回调实际端口(port=0 随机端口时获取) */
22
+ onListen?: (port: number) => void;
23
+ }
24
+ /**
25
+ * 启动 --http 常驻 server。阻塞直到进程退出(Ctrl-C / 关闭 → 释放锁)。
26
+ * 返回一个 async 函数:调用后等待关闭(测试用)。
27
+ */
28
+ export declare function serveHttp(opts: HttpServeOptions): Promise<() => Promise<void>>;
package/dist/http.js ADDED
@@ -0,0 +1,119 @@
1
+ import { createServer } from 'node:http';
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
+ import { acquireInstanceLock, releaseInstanceLock } from './runner.js';
5
+ import { buildCtx, registerTools } from './server.js';
6
+ import { collectStatus, renderStatusHtml } from './status.js';
7
+ /**
8
+ * M11d D-H1/D-H2/D-H3:--http 常驻模式(StreamableHTTPServerTransport)。
9
+ * - POST /mcp:JSON-RPC(streamable HTTP 主端点)
10
+ * - GET /mcp:SSE 流(可选,SDK 支持时提供)
11
+ * - GET /health:健康检查(只读状态页复用,M11e)
12
+ * - GET /status.json:自描述状态 JSON(D-S1;与状态页同一数据源,只读)
13
+ * - 与 stdio 共用 data/.lock(D-R2 互斥:两个模式不能同时跑)
14
+ * - 默认端口 3081(--http-port 覆盖);--http-token 可选开启环回认证
15
+ */
16
+ export const DEFAULT_HTTP_PORT = 3081;
17
+ /** 简单 token 校验(可选;Authorization: Bearer <token>) */
18
+ function checkToken(req, token) {
19
+ const auth = req.headers.authorization ?? '';
20
+ return auth === `Bearer ${token}`;
21
+ }
22
+ /**
23
+ * 启动 --http 常驻 server。阻塞直到进程退出(Ctrl-C / 关闭 → 释放锁)。
24
+ * 返回一个 async 函数:调用后等待关闭(测试用)。
25
+ */
26
+ export async function serveHttp(opts) {
27
+ // D-H2:与 stdio 共用单实例锁
28
+ if (!acquireInstanceLock(opts.dataDir)) {
29
+ throw new Error('另一个 flow-rpa 实例正在运行(data/.lock 锁持有中);请先退出再启动');
30
+ }
31
+ const port = opts.port ?? DEFAULT_HTTP_PORT;
32
+ const ctx = buildCtx(opts.flowsDir, opts.dataDir, opts.config, 'http');
33
+ const transports = new Set();
34
+ let closed = false;
35
+ const closeAll = async () => {
36
+ if (closed)
37
+ return;
38
+ closed = true;
39
+ await Promise.all([...transports].map((t) => t.close().catch(() => undefined)));
40
+ releaseInstanceLock(opts.dataDir);
41
+ };
42
+ const httpServer = createServer(async (req, res) => {
43
+ // 可选 token 校验(非 /health)
44
+ if (opts.token && req.url !== '/health' && !checkToken(req, opts.token)) {
45
+ res.writeHead(401, { 'Content-Type': 'application/json' });
46
+ res.end(JSON.stringify({ error: 'unauthorized' }));
47
+ return;
48
+ }
49
+ // D-H3:健康检查(M11e 状态页复用)
50
+ if (req.method === 'GET' && req.url === '/health') {
51
+ res.writeHead(200, { 'Content-Type': 'application/json' });
52
+ res.end(JSON.stringify({ ok: true, mode: 'http', port }));
53
+ return;
54
+ }
55
+ // D-S1:/status.json 自描述(只读;与状态页同一数据源)
56
+ if (req.method === 'GET' && req.url === '/status.json') {
57
+ res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
58
+ res.end(JSON.stringify(await collectStatus(ctx), null, 2));
59
+ return;
60
+ }
61
+ // M11e D-P1:只读状态页(GET /,HTML)
62
+ if (req.method === 'GET' && req.url === '/') {
63
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
64
+ res.end(await renderStatusHtml(ctx));
65
+ return;
66
+ }
67
+ // MCP 端点:stateless 模式(sessionIdGenerator: undefined)
68
+ // SDK 约束:stateless 下每请求新建 Server + transport(不能共享 Server 连接多 transport)
69
+ if (req.url === '/mcp' && (req.method === 'POST' || req.method === 'GET')) {
70
+ const transport = new StreamableHTTPServerTransport({
71
+ sessionIdGenerator: undefined,
72
+ });
73
+ transports.add(transport);
74
+ transport.onclose = () => {
75
+ transports.delete(transport);
76
+ };
77
+ const sessionServer = new Server({ name: 'flow-rpa', version: '0.1.0-ts' }, { capabilities: { tools: {} } });
78
+ registerTools(sessionServer, ctx);
79
+ // 收集 body(POST JSON-RPC)
80
+ let body = undefined;
81
+ if (req.method === 'POST') {
82
+ body = await new Promise((resolve, reject) => {
83
+ const chunks = [];
84
+ req.on('data', (c) => chunks.push(c));
85
+ req.on('end', () => {
86
+ try {
87
+ resolve(chunks.length > 0 ? JSON.parse(Buffer.concat(chunks).toString('utf8')) : undefined);
88
+ }
89
+ catch (e) {
90
+ reject(e);
91
+ }
92
+ });
93
+ req.on('error', reject);
94
+ });
95
+ }
96
+ await sessionServer.connect(transport);
97
+ await transport.handleRequest(req, res, body);
98
+ return;
99
+ }
100
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
101
+ res.end('not found');
102
+ });
103
+ // 优雅退出:Ctrl-C / SIGTERM → 释放锁(D-H2 断言 3)
104
+ const shutdown = () => {
105
+ void closeAll().then(() => httpServer.close());
106
+ };
107
+ process.on('SIGINT', shutdown);
108
+ process.on('SIGTERM', shutdown);
109
+ await new Promise((resolve) => {
110
+ httpServer.listen(port, () => {
111
+ const addr = httpServer.address();
112
+ const actual = typeof addr === 'object' && addr !== null ? addr.port : port;
113
+ opts.onListen?.(actual);
114
+ resolve();
115
+ });
116
+ });
117
+ return closeAll;
118
+ }
119
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ import { configFromCli, parseCli, runCliCommand } from './cli.js';
3
+ import { serveStdio } from './server.js';
4
+ import { serveHttp } from './http.js';
5
+ /**
6
+ * flow-app —— flow-rpa 应用壳(MCP server)。
7
+ * 用法见 cli.ts 注释(参数兼容 Rust 版:--flows/--data/--mock/--port/--edge/
8
+ * --platform-url/--platform-token/list/validate + M11d --http/--http-port/--http-token)。
9
+ * 模式:缺省 stdio 传输;--http 常驻(StreamableHTTPServerTransport,端口 3081)。
10
+ */
11
+ async function main() {
12
+ const opts = parseCli(process.argv.slice(2));
13
+ // CLI 子命令(list / validate / install-skill)直接处理退出
14
+ if (runCliCommand(opts))
15
+ return;
16
+ const config = configFromCli(opts);
17
+ try {
18
+ if (opts.http) {
19
+ // M11d:--http 常驻(与 stdio 互斥锁)
20
+ const close = await serveHttp({
21
+ flowsDir: opts.flowsDir,
22
+ dataDir: opts.dataDir,
23
+ config,
24
+ port: opts.httpPort,
25
+ token: opts.httpToken,
26
+ });
27
+ // 阻塞直到关闭(Ctrl-C / SIGTERM)
28
+ await new Promise((resolve) => {
29
+ const onShutdown = () => resolve();
30
+ process.once('SIGINT', onShutdown);
31
+ process.once('SIGTERM', onShutdown);
32
+ });
33
+ await close();
34
+ return;
35
+ }
36
+ await serveStdio(opts.flowsDir, opts.dataDir, config);
37
+ }
38
+ catch (e) {
39
+ console.error(`[flow-rpa] MCP server 启动失败: ${e instanceof Error ? e.message : String(e)}`);
40
+ process.exit(1);
41
+ }
42
+ }
43
+ main().catch((e) => {
44
+ console.error(`[flow-rpa] 异常退出: ${e instanceof Error ? e.message : String(e)}`);
45
+ process.exit(1);
46
+ });
47
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC;;;;;GAKG;AAEH,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5C,iDAAiD;IACjD,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAM;IAC/B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAClC,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,8BAA8B;YAC9B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC;gBAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,MAAM;gBACN,IAAI,EAAE,IAAI,CAAC,QAAQ;gBACnB,KAAK,EAAE,IAAI,CAAC,SAAS;aACtB,CAAC,CAAA;YACF,2BAA2B;YAC3B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAA;gBAClC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;gBAClC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;YACrC,CAAC,CAAC,CAAA;YACF,MAAM,KAAK,EAAE,CAAA;YACb,OAAM;QACR,CAAC;QACD,MAAM,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACvD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,35 @@
1
+ import { type Flow } from '@qing3a/flow-rpa-engine/src/validate.js';
2
+ /**
3
+ * FlowRegistry —— 流程注册表(移植 Rust `server.rs` FlowRegistry)。
4
+ * 扫描 flows/ 目录下各子目录的 flow.json,缓存解析结果。
5
+ */
6
+ /** 流程参数声明(D-R6;list_flows 返回,供 Agent 组装 vars) */
7
+ export interface FlowInputDecl {
8
+ name: string;
9
+ /** 必填(D-R6:缺省 false;缺 required 参数时 run_flow 报「缺少必填参数」) */
10
+ required: boolean;
11
+ description?: string;
12
+ }
13
+ /** 流程摘要(list_flows 返回) */
14
+ export interface FlowSummary {
15
+ id: string;
16
+ name: string;
17
+ version: number;
18
+ path: string;
19
+ inputs: FlowInputDecl[];
20
+ }
21
+ export declare class FlowRegistry {
22
+ private readonly flowsDir;
23
+ /** flow_id → 已解析的流程定义(缓存) */
24
+ private cache;
25
+ constructor(flowsDir: string);
26
+ /** 扫描 flows/ 下各子目录的 flow.json */
27
+ list(): FlowSummary[];
28
+ get(flowId: string): {
29
+ version: number;
30
+ raw: string;
31
+ flow: Flow;
32
+ } | undefined;
33
+ /** 流程目录(pkg_update 替换用) */
34
+ flowsDirOf(): string;
35
+ }
@@ -0,0 +1,64 @@
1
+ import { readdirSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { parseFlow } from '@qing3a/flow-rpa-engine/src/validate.js';
4
+ export class FlowRegistry {
5
+ flowsDir;
6
+ /** flow_id → 已解析的流程定义(缓存) */
7
+ cache = new Map();
8
+ constructor(flowsDir) {
9
+ this.flowsDir = flowsDir;
10
+ }
11
+ /** 扫描 flows/ 下各子目录的 flow.json */
12
+ list() {
13
+ const out = [];
14
+ let entries;
15
+ try {
16
+ entries = readdirSync(this.flowsDir, { withFileTypes: true })
17
+ .filter((e) => e.isDirectory())
18
+ .map((e) => e.name);
19
+ }
20
+ catch {
21
+ return [];
22
+ }
23
+ for (const name of entries) {
24
+ const flowPath = join(this.flowsDir, name, 'flow.json');
25
+ let raw;
26
+ try {
27
+ raw = readFileSync(flowPath, 'utf8');
28
+ }
29
+ catch {
30
+ continue;
31
+ }
32
+ try {
33
+ const flow = parseFlow(raw);
34
+ out.push({
35
+ id: flow.id,
36
+ name: flow.name,
37
+ version: flow.version,
38
+ path: flowPath,
39
+ inputs: (flow.inputs ?? []).map((i) => ({
40
+ name: i.name,
41
+ required: i.required === true,
42
+ ...(i.description ? { description: i.description } : {}),
43
+ })),
44
+ });
45
+ this.cache.set(flow.id, { version: flow.version, raw, flow });
46
+ }
47
+ catch {
48
+ // 解析失败跳过(list 不报错)
49
+ }
50
+ }
51
+ out.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
52
+ return out;
53
+ }
54
+ get(flowId) {
55
+ if (this.cache.size === 0)
56
+ this.list();
57
+ return this.cache.get(flowId);
58
+ }
59
+ /** 流程目录(pkg_update 替换用) */
60
+ flowsDirOf() {
61
+ return this.flowsDir;
62
+ }
63
+ }
64
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}