@kevisual/router 0.0.59 → 0.0.61
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/agent/app.ts +5 -0
- package/agent/gen/index.ts +205 -0
- package/agent/gen.ts +42 -0
- package/agent/main.ts +6 -0
- package/agent/routes/index.ts +14 -0
- package/agent/routes/route-create.ts +45 -0
- package/dist/app.d.ts +5 -0
- package/dist/app.js +19363 -0
- package/dist/opencode.d.ts +2 -1
- package/dist/opencode.js +362 -9
- package/dist/router-browser.d.ts +17 -2
- package/dist/router-browser.js +407 -10
- package/dist/router.d.ts +17 -3
- package/dist/router.js +15656 -15613
- package/package.json +5 -2
- package/src/app.ts +0 -1
- package/src/browser.ts +2 -0
- package/src/index.ts +2 -0
- package/src/opencode.ts +4 -0
- package/src/result/error.ts +2 -2
- package/src/route.ts +6 -5
- package/src/test/mini.ts +14 -0
- package/src/test/run-mini.ts +56 -0
- package/src/utils/listen-process.ts +60 -12
package/package.json
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@kevisual/router",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.61",
|
|
5
5
|
"description": "",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/router.js",
|
|
8
8
|
"types": "./dist/router.d.ts",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "npm run clean && rollup -c",
|
|
11
|
-
"
|
|
11
|
+
"postbuild": "bun run bun.config.ts",
|
|
12
12
|
"watch": "rollup -c -w",
|
|
13
13
|
"clean": "rm -rf dist"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"src",
|
|
18
|
+
"agent",
|
|
18
19
|
"auto.ts",
|
|
19
20
|
"mod.ts"
|
|
20
21
|
],
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
"@types/ws": "^8.18.1",
|
|
40
41
|
"@types/xml2js": "^0.4.14",
|
|
41
42
|
"eventemitter3": "^5.0.4",
|
|
43
|
+
"fast-glob": "^3.3.3",
|
|
42
44
|
"nanoid": "^5.1.6",
|
|
43
45
|
"path-to-regexp": "^8.3.0",
|
|
44
46
|
"rollup": "^4.55.2",
|
|
@@ -80,6 +82,7 @@
|
|
|
80
82
|
"types": "./dist/router-simple.d.ts"
|
|
81
83
|
},
|
|
82
84
|
"./opencode": "./dist/opencode.js",
|
|
85
|
+
"./skill": "./dist/app.js",
|
|
83
86
|
"./define": {
|
|
84
87
|
"import": "./dist/router-define.js",
|
|
85
88
|
"require": "./dist/router-define.js",
|
package/src/app.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { QueryRouter, Route, RouteContext, RouteOpts } from './route.ts';
|
|
|
2
2
|
import { ServerNode, ServerNodeOpts } from './server/server.ts';
|
|
3
3
|
import { HandleCtx } from './server/server-base.ts';
|
|
4
4
|
import { ServerType } from './server/server-type.ts';
|
|
5
|
-
import { CustomError } from './result/error.ts';
|
|
6
5
|
import { handleServer } from './server/handle-server.ts';
|
|
7
6
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
8
7
|
import { isBun } from './utils/is-engine.ts';
|
package/src/browser.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -13,6 +13,8 @@ export { createSkill, tool } from './route.ts';
|
|
|
13
13
|
export { CustomError } from './result/error.ts';
|
|
14
14
|
|
|
15
15
|
export * from './router-define.ts';
|
|
16
|
+
|
|
17
|
+
export { MockProcess } from './utils/listen-process.ts'
|
|
16
18
|
// --- 以上同步更新至 browser.ts ---
|
|
17
19
|
|
|
18
20
|
export { ServerNode, handleServer } from './server/index.ts';
|
package/src/opencode.ts
CHANGED
|
@@ -50,6 +50,9 @@ export const createRouterAgentPluginFn = (opts?: {
|
|
|
50
50
|
if (!router.hasRoute('call', '')) {
|
|
51
51
|
addCallFn(router as App)
|
|
52
52
|
}
|
|
53
|
+
if (!router.hasRoute('auth', '')) {
|
|
54
|
+
router.route({ path: 'auth', key: '', id: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App)
|
|
55
|
+
}
|
|
53
56
|
const _routes = filter(router.routes, opts?.query || '')
|
|
54
57
|
const routes = _routes.filter(r => {
|
|
55
58
|
const metadata = r.metadata as Skill
|
|
@@ -88,6 +91,7 @@ export const createRouterAgentPluginFn = (opts?: {
|
|
|
88
91
|
}
|
|
89
92
|
return str;
|
|
90
93
|
}
|
|
94
|
+
console.error('调用出错', res);
|
|
91
95
|
return `Error: ${res?.message || '无法获取结果'}`;
|
|
92
96
|
}
|
|
93
97
|
}
|
package/src/result/error.ts
CHANGED
|
@@ -9,10 +9,10 @@ export class CustomError extends Error {
|
|
|
9
9
|
this.name = 'CustomError';
|
|
10
10
|
if (typeof code === 'number') {
|
|
11
11
|
this.code = code;
|
|
12
|
-
this.message = message
|
|
12
|
+
this.message = message!;
|
|
13
13
|
} else {
|
|
14
14
|
this.code = 500;
|
|
15
|
-
this.message = code
|
|
15
|
+
this.message = code!;
|
|
16
16
|
}
|
|
17
17
|
this.tips = tips;
|
|
18
18
|
// 这一步可不写,默认会保存堆栈追踪信息到自定义错误构造函数之前,
|
package/src/route.ts
CHANGED
|
@@ -60,7 +60,7 @@ export type RouteContext<T = { code?: number }, S = any> = {
|
|
|
60
60
|
needSerialize?: boolean;
|
|
61
61
|
} & T;
|
|
62
62
|
export type SimpleObject = Record<string, any>;
|
|
63
|
-
export type Run<T extends SimpleObject = {}> = (ctx: RouteContext<T
|
|
63
|
+
export type Run<T extends SimpleObject = {}> = (ctx: Required<RouteContext<T>>) => Promise<typeof ctx | null | void>;
|
|
64
64
|
|
|
65
65
|
export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
|
|
66
66
|
export type RouteMiddleware =
|
|
@@ -355,7 +355,7 @@ export class QueryRouter {
|
|
|
355
355
|
const middleware = routeMiddleware[i];
|
|
356
356
|
if (middleware) {
|
|
357
357
|
try {
|
|
358
|
-
await middleware.run(ctx);
|
|
358
|
+
await middleware.run(ctx as Required<RouteContext>);
|
|
359
359
|
} catch (e) {
|
|
360
360
|
if (route?.isDebug) {
|
|
361
361
|
console.error('=====debug====:middlerware error');
|
|
@@ -385,7 +385,7 @@ export class QueryRouter {
|
|
|
385
385
|
if (route) {
|
|
386
386
|
if (route.run) {
|
|
387
387
|
try {
|
|
388
|
-
await route.run(ctx);
|
|
388
|
+
await route.run(ctx as Required<RouteContext>);
|
|
389
389
|
} catch (e) {
|
|
390
390
|
if (route?.isDebug) {
|
|
391
391
|
console.error('=====debug====:', 'router run error:', e.message);
|
|
@@ -614,7 +614,8 @@ export class QueryRouter {
|
|
|
614
614
|
}
|
|
615
615
|
/**
|
|
616
616
|
* 等待程序运行, 获取到message的数据,就执行
|
|
617
|
-
*
|
|
617
|
+
* params 是预设参数,默认path为main
|
|
618
|
+
*
|
|
618
619
|
* emitter = process
|
|
619
620
|
* -- .exit
|
|
620
621
|
* -- .on
|
|
@@ -631,7 +632,7 @@ export class QueryRouter {
|
|
|
631
632
|
if (getList) {
|
|
632
633
|
this.createRouteList(opts?.force ?? false, opts?.filter);
|
|
633
634
|
}
|
|
634
|
-
return listenProcess({ app: this, params, ...opts });
|
|
635
|
+
return listenProcess({ app: this as any, params, ...opts });
|
|
635
636
|
}
|
|
636
637
|
}
|
|
637
638
|
|
package/src/test/mini.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { fork } from 'child_process'
|
|
2
|
+
|
|
3
|
+
export type RunCodeParams = {
|
|
4
|
+
path?: string;
|
|
5
|
+
key?: string;
|
|
6
|
+
payload?: string;
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
type RunCode = {
|
|
10
|
+
// 调用进程的功能
|
|
11
|
+
success?: boolean
|
|
12
|
+
data?: {
|
|
13
|
+
// 调用router的结果
|
|
14
|
+
code?: number
|
|
15
|
+
data?: any
|
|
16
|
+
message?: string
|
|
17
|
+
[key: string]: any
|
|
18
|
+
};
|
|
19
|
+
error?: any
|
|
20
|
+
timestamp?: string
|
|
21
|
+
[key: string]: any
|
|
22
|
+
}
|
|
23
|
+
export const runCode = async (tsPath: string, params: RunCodeParams = {}): Promise<RunCode> => {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
// 使用 Bun 的 fork 模式启动子进程
|
|
26
|
+
const child = fork(tsPath)
|
|
27
|
+
|
|
28
|
+
// 监听来自子进程的消息
|
|
29
|
+
child.on('message', (msg: RunCode) => {
|
|
30
|
+
resolve(msg)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// child.on('exit', (code, signal) => {
|
|
34
|
+
// console.log('子进程已退出,退出码:', code, '信号:', signal)
|
|
35
|
+
// })
|
|
36
|
+
|
|
37
|
+
// child.on('close', (code, signal) => {
|
|
38
|
+
// console.log('子进程已关闭,退出码:', code, '信号:', signal)
|
|
39
|
+
// })
|
|
40
|
+
|
|
41
|
+
child.on('error', (error) => {
|
|
42
|
+
resolve({
|
|
43
|
+
success: false, error: error?.message
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
// 向子进程发送消息
|
|
48
|
+
child.send(params)
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
import path from 'node:path'
|
|
52
|
+
const res =await runCode(path.join(process.cwd(), './src/test/mini.ts'), {
|
|
53
|
+
// path: 'main'
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
console.log('res', res)
|
|
@@ -1,23 +1,63 @@
|
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
|
+
import { QueryRouterServer } from "../route.ts"
|
|
3
|
+
export class MockProcess {
|
|
4
|
+
emitter?: EventEmitter
|
|
5
|
+
process?: NodeJS.Process;
|
|
6
|
+
constructor(opts?: { emitter?: EventEmitter, isNode?: boolean }) {
|
|
7
|
+
this.emitter = opts?.emitter || new EventEmitter();
|
|
8
|
+
const isNode = opts?.isNode ?? true;
|
|
9
|
+
if (isNode) {
|
|
10
|
+
this.process = globalThis?.process;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
send(data?: any, callback?: (err?: Error) => void) {
|
|
14
|
+
if (this.process) {
|
|
15
|
+
this.process?.send?.(data, (err?: Error) => {
|
|
16
|
+
callback(err)
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
this.emitter.emit('send', data)
|
|
20
|
+
}
|
|
21
|
+
exit(flag: number = 0) {
|
|
22
|
+
if (this.process) {
|
|
23
|
+
this.process?.exit?.(flag)
|
|
24
|
+
}
|
|
25
|
+
this.emitter.emit('exit', flag)
|
|
26
|
+
}
|
|
27
|
+
on(fn: (msg?: any) => any) {
|
|
28
|
+
if (this.process) {
|
|
29
|
+
this.process.on('message', fn)
|
|
30
|
+
}
|
|
31
|
+
this.emitter.on('message', fn)
|
|
32
|
+
}
|
|
33
|
+
desctroy() {
|
|
34
|
+
if (this.emitter) {
|
|
35
|
+
this.emitter = undefined;
|
|
36
|
+
}
|
|
37
|
+
this.process = undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
1
40
|
export type ListenProcessOptions = {
|
|
2
|
-
app?:
|
|
3
|
-
|
|
41
|
+
app?: QueryRouterServer; // 传入的应用实例
|
|
42
|
+
mockProcess?: MockProcess; // 可选的事件发射器
|
|
4
43
|
params?: any; // 可选的参数
|
|
5
|
-
timeout?: number; // 可选的超时时间 (单位: 毫秒)
|
|
44
|
+
timeout?: number; // 可选的超时时间 (单位: 毫秒) 默认 10 分钟
|
|
6
45
|
};
|
|
7
|
-
export const listenProcess = async ({ app,
|
|
8
|
-
const process =
|
|
46
|
+
export const listenProcess = async ({ app, mockProcess, params, timeout = 10 * 60 * 60 * 1000 }: ListenProcessOptions) => {
|
|
47
|
+
const process = mockProcess || new MockProcess();
|
|
9
48
|
let isEnd = false;
|
|
10
49
|
const timer = setTimeout(() => {
|
|
11
50
|
if (isEnd) return;
|
|
12
51
|
isEnd = true;
|
|
13
|
-
process.send?.({ success: false, error: 'Timeout' })
|
|
14
|
-
|
|
52
|
+
process.send?.({ success: false, error: 'Timeout' }, () => {
|
|
53
|
+
process.exit?.(1);
|
|
54
|
+
});
|
|
15
55
|
}, timeout);
|
|
16
56
|
|
|
17
57
|
// 监听来自主进程的消息
|
|
18
58
|
const getParams = async (): Promise<any> => {
|
|
19
59
|
return new Promise((resolve) => {
|
|
20
|
-
process.on(
|
|
60
|
+
process.on((msg) => {
|
|
21
61
|
if (isEnd) return;
|
|
22
62
|
isEnd = true;
|
|
23
63
|
clearTimeout(timer);
|
|
@@ -27,9 +67,16 @@ export const listenProcess = async ({ app, emitter, params, timeout = 10 * 60 *
|
|
|
27
67
|
}
|
|
28
68
|
|
|
29
69
|
try {
|
|
30
|
-
|
|
70
|
+
/**
|
|
71
|
+
* 如果不提供path,默认是main
|
|
72
|
+
*/
|
|
73
|
+
const {
|
|
74
|
+
path = 'main',
|
|
75
|
+
payload = {},
|
|
76
|
+
...rest
|
|
77
|
+
} = await getParams()
|
|
31
78
|
// 执行主要逻辑
|
|
32
|
-
const result = await app.
|
|
79
|
+
const result = await app.run({ path, ...params, ...rest, payload: { ...params?.payload, ...payload } })
|
|
33
80
|
// 发送结果回主进程
|
|
34
81
|
const response = {
|
|
35
82
|
success: true,
|
|
@@ -37,14 +84,15 @@ export const listenProcess = async ({ app, emitter, params, timeout = 10 * 60 *
|
|
|
37
84
|
timestamp: new Date().toISOString()
|
|
38
85
|
}
|
|
39
86
|
|
|
40
|
-
process.send?.(response, (
|
|
87
|
+
process.send?.(response, () => {
|
|
41
88
|
process.exit?.(0)
|
|
42
89
|
})
|
|
43
90
|
} catch (error) {
|
|
44
91
|
process.send?.({
|
|
45
92
|
success: false,
|
|
46
93
|
error: error.message
|
|
94
|
+
}, () => {
|
|
95
|
+
process.exit?.(1)
|
|
47
96
|
})
|
|
48
|
-
process.exit?.(1)
|
|
49
97
|
}
|
|
50
98
|
}
|