@kevisual/router 0.0.74 → 0.0.76
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/routes/route-create.ts +37 -3
- package/dist/app.js +75 -14
- package/dist/opencode.d.ts +8 -3
- package/dist/opencode.js +27 -5
- package/dist/router-browser.d.ts +1 -2
- package/dist/router-browser.js +18 -6
- package/dist/router-define.d.ts +0 -2
- package/dist/router.d.ts +1 -2
- package/dist/router.js +18 -6
- package/dist/ws.d.ts +0 -2
- package/package.json +2 -3
- package/src/opencode.ts +28 -6
- package/src/route.ts +23 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { app, createSkill, tool } from '../app.ts';
|
|
2
2
|
import * as docs from '../gen/index.ts'
|
|
3
3
|
import * as pkgs from '../../package.json' assert { type: 'json' };
|
|
4
|
+
import z from 'zod';
|
|
4
5
|
app.route({
|
|
5
6
|
path: 'router-skill',
|
|
6
7
|
key: 'create-route',
|
|
@@ -32,14 +33,47 @@ app.route({
|
|
|
32
33
|
}
|
|
33
34
|
}).addTo(app);
|
|
34
35
|
|
|
35
|
-
//
|
|
36
|
+
// 获取最新router版本号
|
|
36
37
|
app.route({
|
|
37
38
|
path: 'router-skill',
|
|
38
39
|
key: 'version',
|
|
39
|
-
description: '
|
|
40
|
+
description: '获取最新router版本号',
|
|
40
41
|
middleware: ['auth'],
|
|
42
|
+
metadata: {
|
|
43
|
+
tags: ['opencode'],
|
|
44
|
+
...createSkill({
|
|
45
|
+
skill: 'router-skill-version',
|
|
46
|
+
title: '获取最新router版本号',
|
|
47
|
+
summary: '获取最新router版本号',
|
|
48
|
+
args: {}
|
|
49
|
+
})
|
|
50
|
+
},
|
|
41
51
|
}).define(async (ctx) => {
|
|
42
52
|
ctx.body = {
|
|
43
53
|
content: pkgs.version || 'unknown'
|
|
44
54
|
}
|
|
45
|
-
}).addTo(app);
|
|
55
|
+
}).addTo(app);
|
|
56
|
+
|
|
57
|
+
// 执行技能test-route-skill,name为abearxiong
|
|
58
|
+
app.route({
|
|
59
|
+
path: 'route-skill',
|
|
60
|
+
key: 'test',
|
|
61
|
+
description: '测试路由技能',
|
|
62
|
+
middleware: ['auth'],
|
|
63
|
+
metadata: {
|
|
64
|
+
tags: ['opencode'],
|
|
65
|
+
...createSkill({
|
|
66
|
+
skill: 'test-route-skill',
|
|
67
|
+
title: '测试路由技能',
|
|
68
|
+
summary: '测试路由技能是否正常工作',
|
|
69
|
+
args: z.object({
|
|
70
|
+
name: z.string().describe('名字'),
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
},
|
|
74
|
+
}).define(async (ctx) => {
|
|
75
|
+
const name = ctx.query.name || 'unknown';
|
|
76
|
+
ctx.body = {
|
|
77
|
+
content: '测试成功,你好 ' + name
|
|
78
|
+
}
|
|
79
|
+
}).addTo(app)
|
package/dist/app.js
CHANGED
|
@@ -16745,6 +16745,9 @@ function date4(params) {
|
|
|
16745
16745
|
|
|
16746
16746
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
16747
16747
|
config(en_default());
|
|
16748
|
+
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/index.js
|
|
16749
|
+
var zod_default = exports_external;
|
|
16750
|
+
|
|
16748
16751
|
// node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
|
|
16749
16752
|
import { webcrypto as crypto } from "node:crypto";
|
|
16750
16753
|
var POOL_SIZE_MULTIPLIER = 128;
|
|
@@ -16799,6 +16802,12 @@ var tool = {
|
|
|
16799
16802
|
schema: exports_external
|
|
16800
16803
|
};
|
|
16801
16804
|
var createSkill = (skill) => {
|
|
16805
|
+
if (skill.tags) {
|
|
16806
|
+
const hasOpencode = skill.tags.includes("opencode");
|
|
16807
|
+
if (!hasOpencode) {
|
|
16808
|
+
skill.tags.push("opencode");
|
|
16809
|
+
}
|
|
16810
|
+
}
|
|
16802
16811
|
return {
|
|
16803
16812
|
args: {},
|
|
16804
16813
|
...skill
|
|
@@ -16815,7 +16824,6 @@ class Route {
|
|
|
16815
16824
|
metadata;
|
|
16816
16825
|
middleware;
|
|
16817
16826
|
type = "route";
|
|
16818
|
-
data;
|
|
16819
16827
|
isDebug;
|
|
16820
16828
|
constructor(path = "", key = "", opts) {
|
|
16821
16829
|
if (!path) {
|
|
@@ -16907,18 +16915,21 @@ class Route {
|
|
|
16907
16915
|
addTo(router, opts) {
|
|
16908
16916
|
router.add(this, opts);
|
|
16909
16917
|
}
|
|
16910
|
-
setData(data) {
|
|
16911
|
-
this.data = data;
|
|
16912
|
-
return this;
|
|
16913
|
-
}
|
|
16914
16918
|
throw(...args) {
|
|
16915
16919
|
throw new CustomError(...args);
|
|
16916
16920
|
}
|
|
16917
16921
|
}
|
|
16922
|
+
var extractArgs = (args) => {
|
|
16923
|
+
if (args && typeof args === "object" && typeof args.shape === "object") {
|
|
16924
|
+
return args.shape;
|
|
16925
|
+
}
|
|
16926
|
+
return args || {};
|
|
16927
|
+
};
|
|
16918
16928
|
var toJSONSchema2 = (route) => {
|
|
16919
16929
|
const pickValues = pick(route, pickValue);
|
|
16920
16930
|
if (pickValues?.metadata?.args) {
|
|
16921
|
-
|
|
16931
|
+
let args = pickValues.metadata.args;
|
|
16932
|
+
args = extractArgs(args);
|
|
16922
16933
|
const keys = Object.keys(args);
|
|
16923
16934
|
const newArgs = {};
|
|
16924
16935
|
for (let key of keys) {
|
|
@@ -16937,6 +16948,10 @@ var fromJSONSchema2 = (route) => {
|
|
|
16937
16948
|
const args = route?.metadata?.args;
|
|
16938
16949
|
if (!args)
|
|
16939
16950
|
return route;
|
|
16951
|
+
if (args["$schema"] || args.type === "object" && args.properties && typeof args.properties === "object") {
|
|
16952
|
+
route.metadata.args = exports_external.fromJSONSchema(args);
|
|
16953
|
+
return route;
|
|
16954
|
+
}
|
|
16940
16955
|
const keys = Object.keys(args);
|
|
16941
16956
|
const newArgs = {};
|
|
16942
16957
|
for (let key of keys) {
|
|
@@ -19175,8 +19190,12 @@ var addCallFn = (app2) => {
|
|
|
19175
19190
|
tags: ["opencode"],
|
|
19176
19191
|
...createSkill({
|
|
19177
19192
|
skill: "call-app",
|
|
19178
|
-
title: "调用app
|
|
19179
|
-
summary:
|
|
19193
|
+
title: "调用app应用,非技能模块",
|
|
19194
|
+
summary: `调用router的应用(非技能模块),适用于需要直接调用应用而不是技能的场景
|
|
19195
|
+
条件1: 参数path(string), key(string), payload(object)
|
|
19196
|
+
条件2: 当前的应用调用的模式不是技能
|
|
19197
|
+
|
|
19198
|
+
`,
|
|
19180
19199
|
args: {
|
|
19181
19200
|
path: tool.schema.string().describe("应用路径,例如 cnb"),
|
|
19182
19201
|
key: tool.schema.string().optional().describe("应用key,例如 list-repos"),
|
|
@@ -19196,6 +19215,7 @@ var addCallFn = (app2) => {
|
|
|
19196
19215
|
}).addTo(app2);
|
|
19197
19216
|
};
|
|
19198
19217
|
var createRouterAgentPluginFn = (opts) => {
|
|
19218
|
+
new Promise((resolve) => setTimeout(resolve, 100));
|
|
19199
19219
|
let router = opts?.router;
|
|
19200
19220
|
if (!router) {
|
|
19201
19221
|
const app2 = useContextKey("app");
|
|
@@ -19213,6 +19233,9 @@ var createRouterAgentPluginFn = (opts) => {
|
|
|
19213
19233
|
const _routes = filter(router.routes, opts?.query || "");
|
|
19214
19234
|
const routes = _routes.filter((r) => {
|
|
19215
19235
|
const metadata = r.metadata;
|
|
19236
|
+
if (metadata && metadata.skill && metadata.summary) {
|
|
19237
|
+
return true;
|
|
19238
|
+
}
|
|
19216
19239
|
if (metadata && metadata.tags && metadata.tags.includes("opencode")) {
|
|
19217
19240
|
return !!metadata.skill;
|
|
19218
19241
|
}
|
|
@@ -19226,15 +19249,16 @@ var createRouterAgentPluginFn = (opts) => {
|
|
|
19226
19249
|
tool: {
|
|
19227
19250
|
...routes.reduce((acc, route) => {
|
|
19228
19251
|
const metadata = route.metadata;
|
|
19252
|
+
let args = extractArgs2(metadata?.args);
|
|
19229
19253
|
acc[metadata.skill] = {
|
|
19230
19254
|
name: metadata.title || metadata.skill,
|
|
19231
19255
|
description: metadata.summary || "",
|
|
19232
|
-
args
|
|
19233
|
-
async execute(
|
|
19256
|
+
args,
|
|
19257
|
+
async execute(args2) {
|
|
19234
19258
|
const res = await router.run({
|
|
19235
19259
|
path: route.path,
|
|
19236
19260
|
key: route.key,
|
|
19237
|
-
payload:
|
|
19261
|
+
payload: args2
|
|
19238
19262
|
}, { appId: router.appId });
|
|
19239
19263
|
if (res.code === 200) {
|
|
19240
19264
|
if (res.data?.content) {
|
|
@@ -19261,6 +19285,12 @@ var createRouterAgentPluginFn = (opts) => {
|
|
|
19261
19285
|
};
|
|
19262
19286
|
return AgentPlugin;
|
|
19263
19287
|
};
|
|
19288
|
+
var extractArgs2 = (args) => {
|
|
19289
|
+
if (args && typeof args === "object" && typeof args.shape === "object") {
|
|
19290
|
+
return args.shape;
|
|
19291
|
+
}
|
|
19292
|
+
return args || {};
|
|
19293
|
+
};
|
|
19264
19294
|
|
|
19265
19295
|
// agent/gen/index.ts
|
|
19266
19296
|
var readme = `# router
|
|
@@ -19453,7 +19483,7 @@ app
|
|
|
19453
19483
|
10. **中间件找不到会返回 404**,错误信息中会包含找不到的中间件列表。
|
|
19454
19484
|
`;
|
|
19455
19485
|
// package.json
|
|
19456
|
-
var version2 = "0.0.
|
|
19486
|
+
var version2 = "0.0.76";
|
|
19457
19487
|
|
|
19458
19488
|
// agent/routes/route-create.ts
|
|
19459
19489
|
app.route({
|
|
@@ -19493,13 +19523,44 @@ app.route({
|
|
|
19493
19523
|
app.route({
|
|
19494
19524
|
path: "router-skill",
|
|
19495
19525
|
key: "version",
|
|
19496
|
-
description: "
|
|
19497
|
-
middleware: ["auth"]
|
|
19526
|
+
description: "获取最新router版本号",
|
|
19527
|
+
middleware: ["auth"],
|
|
19528
|
+
metadata: {
|
|
19529
|
+
tags: ["opencode"],
|
|
19530
|
+
...createSkill({
|
|
19531
|
+
skill: "router-skill-version",
|
|
19532
|
+
title: "获取最新router版本号",
|
|
19533
|
+
summary: "获取最新router版本号",
|
|
19534
|
+
args: {}
|
|
19535
|
+
})
|
|
19536
|
+
}
|
|
19498
19537
|
}).define(async (ctx) => {
|
|
19499
19538
|
ctx.body = {
|
|
19500
19539
|
content: version2 || "unknown"
|
|
19501
19540
|
};
|
|
19502
19541
|
}).addTo(app);
|
|
19542
|
+
app.route({
|
|
19543
|
+
path: "route-skill",
|
|
19544
|
+
key: "test",
|
|
19545
|
+
description: "测试路由技能",
|
|
19546
|
+
middleware: ["auth"],
|
|
19547
|
+
metadata: {
|
|
19548
|
+
tags: ["opencode"],
|
|
19549
|
+
...createSkill({
|
|
19550
|
+
skill: "test-route-skill",
|
|
19551
|
+
title: "测试路由技能",
|
|
19552
|
+
summary: "测试路由技能是否正常工作",
|
|
19553
|
+
args: zod_default.object({
|
|
19554
|
+
name: zod_default.string().describe("名字")
|
|
19555
|
+
})
|
|
19556
|
+
})
|
|
19557
|
+
}
|
|
19558
|
+
}).define(async (ctx) => {
|
|
19559
|
+
const name = ctx.query.name || "unknown";
|
|
19560
|
+
ctx.body = {
|
|
19561
|
+
content: "测试成功,你好 " + name
|
|
19562
|
+
};
|
|
19563
|
+
}).addTo(app);
|
|
19503
19564
|
|
|
19504
19565
|
// agent/routes/index.ts
|
|
19505
19566
|
if (!app.hasRoute("auth", "")) {
|
package/dist/opencode.d.ts
CHANGED
|
@@ -150,7 +150,6 @@ declare class Route<U = {
|
|
|
150
150
|
metadata?: T;
|
|
151
151
|
middleware?: RouteMiddleware[];
|
|
152
152
|
type?: string;
|
|
153
|
-
data?: any;
|
|
154
153
|
/**
|
|
155
154
|
* 是否开启debug,开启后会打印错误信息
|
|
156
155
|
*/
|
|
@@ -175,7 +174,6 @@ declare class Route<U = {
|
|
|
175
174
|
add: (route: Route) => void;
|
|
176
175
|
[key: string]: any;
|
|
177
176
|
}, opts?: AddOpts): void;
|
|
178
|
-
setData(data: any): this;
|
|
179
177
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
180
178
|
}
|
|
181
179
|
/**
|
|
@@ -719,5 +717,12 @@ declare const createRouterAgentPluginFn: (opts?: {
|
|
|
719
717
|
hooks?: (plugin: PluginInput) => Promise<Hooks>;
|
|
720
718
|
}) => Plugin;
|
|
721
719
|
declare const usePluginInput: () => PluginInput;
|
|
720
|
+
/**
|
|
721
|
+
* 如果args是z.object类型,拆分第一个Object的属性,比如z.object({ name: z.string(), age: z.number() }),拆分成{name: z.string(), age: z.number()}
|
|
722
|
+
* 如果args是普通对象,直接返回
|
|
723
|
+
* @param args
|
|
724
|
+
* @returns
|
|
725
|
+
*/
|
|
726
|
+
declare const extractArgs: (args: any) => any;
|
|
722
727
|
|
|
723
|
-
export { addCallFn, createRouterAgentPluginFn, usePluginInput };
|
|
728
|
+
export { addCallFn, createRouterAgentPluginFn, extractArgs, usePluginInput };
|
package/dist/opencode.js
CHANGED
|
@@ -14339,6 +14339,12 @@ var tool = {
|
|
|
14339
14339
|
schema: exports_external
|
|
14340
14340
|
};
|
|
14341
14341
|
var createSkill = (skill) => {
|
|
14342
|
+
if (skill.tags) {
|
|
14343
|
+
const hasOpencode = skill.tags.includes("opencode");
|
|
14344
|
+
if (!hasOpencode) {
|
|
14345
|
+
skill.tags.push("opencode");
|
|
14346
|
+
}
|
|
14347
|
+
}
|
|
14342
14348
|
return {
|
|
14343
14349
|
args: {},
|
|
14344
14350
|
...skill
|
|
@@ -14699,8 +14705,12 @@ var addCallFn = (app) => {
|
|
|
14699
14705
|
tags: ["opencode"],
|
|
14700
14706
|
...createSkill({
|
|
14701
14707
|
skill: "call-app",
|
|
14702
|
-
title: "调用app
|
|
14703
|
-
summary:
|
|
14708
|
+
title: "调用app应用,非技能模块",
|
|
14709
|
+
summary: `调用router的应用(非技能模块),适用于需要直接调用应用而不是技能的场景
|
|
14710
|
+
条件1: 参数path(string), key(string), payload(object)
|
|
14711
|
+
条件2: 当前的应用调用的模式不是技能
|
|
14712
|
+
|
|
14713
|
+
`,
|
|
14704
14714
|
args: {
|
|
14705
14715
|
path: tool.schema.string().describe("应用路径,例如 cnb"),
|
|
14706
14716
|
key: tool.schema.string().optional().describe("应用key,例如 list-repos"),
|
|
@@ -14720,6 +14730,7 @@ var addCallFn = (app) => {
|
|
|
14720
14730
|
}).addTo(app);
|
|
14721
14731
|
};
|
|
14722
14732
|
var createRouterAgentPluginFn = (opts) => {
|
|
14733
|
+
new Promise((resolve) => setTimeout(resolve, 100));
|
|
14723
14734
|
let router = opts?.router;
|
|
14724
14735
|
if (!router) {
|
|
14725
14736
|
const app = useContextKey("app");
|
|
@@ -14737,6 +14748,9 @@ var createRouterAgentPluginFn = (opts) => {
|
|
|
14737
14748
|
const _routes = filter(router.routes, opts?.query || "");
|
|
14738
14749
|
const routes = _routes.filter((r) => {
|
|
14739
14750
|
const metadata = r.metadata;
|
|
14751
|
+
if (metadata && metadata.skill && metadata.summary) {
|
|
14752
|
+
return true;
|
|
14753
|
+
}
|
|
14740
14754
|
if (metadata && metadata.tags && metadata.tags.includes("opencode")) {
|
|
14741
14755
|
return !!metadata.skill;
|
|
14742
14756
|
}
|
|
@@ -14750,15 +14764,16 @@ var createRouterAgentPluginFn = (opts) => {
|
|
|
14750
14764
|
tool: {
|
|
14751
14765
|
...routes.reduce((acc, route) => {
|
|
14752
14766
|
const metadata = route.metadata;
|
|
14767
|
+
let args = extractArgs(metadata?.args);
|
|
14753
14768
|
acc[metadata.skill] = {
|
|
14754
14769
|
name: metadata.title || metadata.skill,
|
|
14755
14770
|
description: metadata.summary || "",
|
|
14756
|
-
args
|
|
14757
|
-
async execute(
|
|
14771
|
+
args,
|
|
14772
|
+
async execute(args2) {
|
|
14758
14773
|
const res = await router.run({
|
|
14759
14774
|
path: route.path,
|
|
14760
14775
|
key: route.key,
|
|
14761
|
-
payload:
|
|
14776
|
+
payload: args2
|
|
14762
14777
|
}, { appId: router.appId });
|
|
14763
14778
|
if (res.code === 200) {
|
|
14764
14779
|
if (res.data?.content) {
|
|
@@ -14788,8 +14803,15 @@ var createRouterAgentPluginFn = (opts) => {
|
|
|
14788
14803
|
var usePluginInput = () => {
|
|
14789
14804
|
return useContextKey("plugin-input");
|
|
14790
14805
|
};
|
|
14806
|
+
var extractArgs = (args) => {
|
|
14807
|
+
if (args && typeof args === "object" && typeof args.shape === "object") {
|
|
14808
|
+
return args.shape;
|
|
14809
|
+
}
|
|
14810
|
+
return args || {};
|
|
14811
|
+
};
|
|
14791
14812
|
export {
|
|
14792
14813
|
usePluginInput,
|
|
14814
|
+
extractArgs,
|
|
14793
14815
|
createRouterAgentPluginFn,
|
|
14794
14816
|
addCallFn
|
|
14795
14817
|
};
|
package/dist/router-browser.d.ts
CHANGED
|
@@ -149,6 +149,7 @@ type Skill<T = SimpleObject$1> = {
|
|
|
149
149
|
skill: string;
|
|
150
150
|
title: string;
|
|
151
151
|
summary?: string;
|
|
152
|
+
tags?: string[];
|
|
152
153
|
args?: {
|
|
153
154
|
[key: string]: any;
|
|
154
155
|
};
|
|
@@ -177,7 +178,6 @@ declare class Route<U = {
|
|
|
177
178
|
metadata?: T;
|
|
178
179
|
middleware?: RouteMiddleware[];
|
|
179
180
|
type?: string;
|
|
180
|
-
data?: any;
|
|
181
181
|
/**
|
|
182
182
|
* 是否开启debug,开启后会打印错误信息
|
|
183
183
|
*/
|
|
@@ -202,7 +202,6 @@ declare class Route<U = {
|
|
|
202
202
|
add: (route: Route) => void;
|
|
203
203
|
[key: string]: any;
|
|
204
204
|
}, opts?: AddOpts): void;
|
|
205
|
-
setData(data: any): this;
|
|
206
205
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
207
206
|
}
|
|
208
207
|
declare const toJSONSchema: (route: RouteInfo) => Pick<RouteInfo, "path" | "key" | "id" | "description" | "type" | "middleware" | "metadata">;
|
package/dist/router-browser.js
CHANGED
|
@@ -13966,6 +13966,12 @@ var tool = {
|
|
|
13966
13966
|
schema: exports_external
|
|
13967
13967
|
};
|
|
13968
13968
|
var createSkill = (skill) => {
|
|
13969
|
+
if (skill.tags) {
|
|
13970
|
+
const hasOpencode = skill.tags.includes("opencode");
|
|
13971
|
+
if (!hasOpencode) {
|
|
13972
|
+
skill.tags.push("opencode");
|
|
13973
|
+
}
|
|
13974
|
+
}
|
|
13969
13975
|
return {
|
|
13970
13976
|
args: {},
|
|
13971
13977
|
...skill
|
|
@@ -13982,7 +13988,6 @@ class Route {
|
|
|
13982
13988
|
metadata;
|
|
13983
13989
|
middleware;
|
|
13984
13990
|
type = "route";
|
|
13985
|
-
data;
|
|
13986
13991
|
isDebug;
|
|
13987
13992
|
constructor(path = "", key = "", opts) {
|
|
13988
13993
|
if (!path) {
|
|
@@ -14074,18 +14079,21 @@ class Route {
|
|
|
14074
14079
|
addTo(router, opts) {
|
|
14075
14080
|
router.add(this, opts);
|
|
14076
14081
|
}
|
|
14077
|
-
setData(data) {
|
|
14078
|
-
this.data = data;
|
|
14079
|
-
return this;
|
|
14080
|
-
}
|
|
14081
14082
|
throw(...args) {
|
|
14082
14083
|
throw new CustomError(...args);
|
|
14083
14084
|
}
|
|
14084
14085
|
}
|
|
14086
|
+
var extractArgs = (args) => {
|
|
14087
|
+
if (args && typeof args === "object" && typeof args.shape === "object") {
|
|
14088
|
+
return args.shape;
|
|
14089
|
+
}
|
|
14090
|
+
return args || {};
|
|
14091
|
+
};
|
|
14085
14092
|
var toJSONSchema2 = (route) => {
|
|
14086
14093
|
const pickValues = pick(route, pickValue);
|
|
14087
14094
|
if (pickValues?.metadata?.args) {
|
|
14088
|
-
|
|
14095
|
+
let args = pickValues.metadata.args;
|
|
14096
|
+
args = extractArgs(args);
|
|
14089
14097
|
const keys = Object.keys(args);
|
|
14090
14098
|
const newArgs = {};
|
|
14091
14099
|
for (let key of keys) {
|
|
@@ -14104,6 +14112,10 @@ var fromJSONSchema2 = (route) => {
|
|
|
14104
14112
|
const args = route?.metadata?.args;
|
|
14105
14113
|
if (!args)
|
|
14106
14114
|
return route;
|
|
14115
|
+
if (args["$schema"] || args.type === "object" && args.properties && typeof args.properties === "object") {
|
|
14116
|
+
route.metadata.args = exports_external.fromJSONSchema(args);
|
|
14117
|
+
return route;
|
|
14118
|
+
}
|
|
14107
14119
|
const keys = Object.keys(args);
|
|
14108
14120
|
const newArgs = {};
|
|
14109
14121
|
for (let key of keys) {
|
package/dist/router-define.d.ts
CHANGED
|
@@ -147,7 +147,6 @@ declare class Route<U = {
|
|
|
147
147
|
metadata?: T;
|
|
148
148
|
middleware?: RouteMiddleware[];
|
|
149
149
|
type?: string;
|
|
150
|
-
data?: any;
|
|
151
150
|
/**
|
|
152
151
|
* 是否开启debug,开启后会打印错误信息
|
|
153
152
|
*/
|
|
@@ -172,7 +171,6 @@ declare class Route<U = {
|
|
|
172
171
|
add: (route: Route) => void;
|
|
173
172
|
[key: string]: any;
|
|
174
173
|
}, opts?: AddOpts): void;
|
|
175
|
-
setData(data: any): this;
|
|
176
174
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
177
175
|
}
|
|
178
176
|
/**
|
package/dist/router.d.ts
CHANGED
|
@@ -155,6 +155,7 @@ type Skill<T = SimpleObject$1> = {
|
|
|
155
155
|
skill: string;
|
|
156
156
|
title: string;
|
|
157
157
|
summary?: string;
|
|
158
|
+
tags?: string[];
|
|
158
159
|
args?: {
|
|
159
160
|
[key: string]: any;
|
|
160
161
|
};
|
|
@@ -183,7 +184,6 @@ declare class Route<U = {
|
|
|
183
184
|
metadata?: T;
|
|
184
185
|
middleware?: RouteMiddleware[];
|
|
185
186
|
type?: string;
|
|
186
|
-
data?: any;
|
|
187
187
|
/**
|
|
188
188
|
* 是否开启debug,开启后会打印错误信息
|
|
189
189
|
*/
|
|
@@ -208,7 +208,6 @@ declare class Route<U = {
|
|
|
208
208
|
add: (route: Route) => void;
|
|
209
209
|
[key: string]: any;
|
|
210
210
|
}, opts?: AddOpts): void;
|
|
211
|
-
setData(data: any): this;
|
|
212
211
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
213
212
|
}
|
|
214
213
|
declare const toJSONSchema: (route: RouteInfo) => Pick<RouteInfo, "path" | "key" | "id" | "description" | "type" | "middleware" | "metadata">;
|
package/dist/router.js
CHANGED
|
@@ -16799,6 +16799,12 @@ var tool = {
|
|
|
16799
16799
|
schema: exports_external
|
|
16800
16800
|
};
|
|
16801
16801
|
var createSkill = (skill) => {
|
|
16802
|
+
if (skill.tags) {
|
|
16803
|
+
const hasOpencode = skill.tags.includes("opencode");
|
|
16804
|
+
if (!hasOpencode) {
|
|
16805
|
+
skill.tags.push("opencode");
|
|
16806
|
+
}
|
|
16807
|
+
}
|
|
16802
16808
|
return {
|
|
16803
16809
|
args: {},
|
|
16804
16810
|
...skill
|
|
@@ -16815,7 +16821,6 @@ class Route {
|
|
|
16815
16821
|
metadata;
|
|
16816
16822
|
middleware;
|
|
16817
16823
|
type = "route";
|
|
16818
|
-
data;
|
|
16819
16824
|
isDebug;
|
|
16820
16825
|
constructor(path = "", key = "", opts) {
|
|
16821
16826
|
if (!path) {
|
|
@@ -16907,18 +16912,21 @@ class Route {
|
|
|
16907
16912
|
addTo(router, opts) {
|
|
16908
16913
|
router.add(this, opts);
|
|
16909
16914
|
}
|
|
16910
|
-
setData(data) {
|
|
16911
|
-
this.data = data;
|
|
16912
|
-
return this;
|
|
16913
|
-
}
|
|
16914
16915
|
throw(...args) {
|
|
16915
16916
|
throw new CustomError(...args);
|
|
16916
16917
|
}
|
|
16917
16918
|
}
|
|
16919
|
+
var extractArgs = (args) => {
|
|
16920
|
+
if (args && typeof args === "object" && typeof args.shape === "object") {
|
|
16921
|
+
return args.shape;
|
|
16922
|
+
}
|
|
16923
|
+
return args || {};
|
|
16924
|
+
};
|
|
16918
16925
|
var toJSONSchema2 = (route) => {
|
|
16919
16926
|
const pickValues = pick(route, pickValue);
|
|
16920
16927
|
if (pickValues?.metadata?.args) {
|
|
16921
|
-
|
|
16928
|
+
let args = pickValues.metadata.args;
|
|
16929
|
+
args = extractArgs(args);
|
|
16922
16930
|
const keys = Object.keys(args);
|
|
16923
16931
|
const newArgs = {};
|
|
16924
16932
|
for (let key of keys) {
|
|
@@ -16937,6 +16945,10 @@ var fromJSONSchema2 = (route) => {
|
|
|
16937
16945
|
const args = route?.metadata?.args;
|
|
16938
16946
|
if (!args)
|
|
16939
16947
|
return route;
|
|
16948
|
+
if (args["$schema"] || args.type === "object" && args.properties && typeof args.properties === "object") {
|
|
16949
|
+
route.metadata.args = exports_external.fromJSONSchema(args);
|
|
16950
|
+
return route;
|
|
16951
|
+
}
|
|
16940
16952
|
const keys = Object.keys(args);
|
|
16941
16953
|
const newArgs = {};
|
|
16942
16954
|
for (let key of keys) {
|
package/dist/ws.d.ts
CHANGED
|
@@ -197,7 +197,6 @@ declare class Route<U = {
|
|
|
197
197
|
metadata?: T;
|
|
198
198
|
middleware?: RouteMiddleware[];
|
|
199
199
|
type?: string;
|
|
200
|
-
data?: any;
|
|
201
200
|
/**
|
|
202
201
|
* 是否开启debug,开启后会打印错误信息
|
|
203
202
|
*/
|
|
@@ -222,7 +221,6 @@ declare class Route<U = {
|
|
|
222
221
|
add: (route: Route) => void;
|
|
223
222
|
[key: string]: any;
|
|
224
223
|
}, opts?: AddOpts): void;
|
|
225
|
-
setData(data: any): this;
|
|
226
224
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
227
225
|
}
|
|
228
226
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@kevisual/router",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.76",
|
|
5
5
|
"description": "",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/router.js",
|
|
@@ -21,14 +21,13 @@
|
|
|
21
21
|
"keywords": [],
|
|
22
22
|
"author": "abearxiong",
|
|
23
23
|
"license": "MIT",
|
|
24
|
-
"packageManager": "pnpm@10.30.0",
|
|
25
24
|
"devDependencies": {
|
|
26
25
|
"@kevisual/code-builder": "^0.0.6",
|
|
27
26
|
"@kevisual/context": "^0.0.6",
|
|
28
27
|
"@kevisual/dts": "^0.0.4",
|
|
29
28
|
"@kevisual/js-filter": "^0.0.5",
|
|
30
29
|
"@kevisual/local-proxy": "^0.0.8",
|
|
31
|
-
"@kevisual/query": "^0.0.
|
|
30
|
+
"@kevisual/query": "^0.0.46",
|
|
32
31
|
"@kevisual/use-config": "^1.0.30",
|
|
33
32
|
"@opencode-ai/plugin": "^1.2.6",
|
|
34
33
|
"@types/bun": "^1.3.9",
|
package/src/opencode.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContextKey } from '@kevisual/context'
|
|
2
|
-
import { createSkill, type QueryRouterServer, tool, type
|
|
2
|
+
import { createSkill, type QueryRouterServer, tool, type Skill } from './route.ts'
|
|
3
3
|
import { type App } from './app.ts'
|
|
4
4
|
import { PluginInput, type Plugin, Hooks } from "@opencode-ai/plugin"
|
|
5
5
|
|
|
@@ -15,8 +15,12 @@ export const addCallFn = (app: App) => {
|
|
|
15
15
|
tags: ['opencode'],
|
|
16
16
|
...createSkill({
|
|
17
17
|
skill: 'call-app',
|
|
18
|
-
title: '调用app
|
|
19
|
-
summary:
|
|
18
|
+
title: '调用app应用,非技能模块',
|
|
19
|
+
summary: `调用router的应用(非技能模块),适用于需要直接调用应用而不是技能的场景
|
|
20
|
+
条件1: 参数path(string), key(string), payload(object)
|
|
21
|
+
条件2: 当前的应用调用的模式不是技能
|
|
22
|
+
|
|
23
|
+
`,
|
|
20
24
|
args: {
|
|
21
25
|
path: tool.schema.string().describe('应用路径,例如 cnb'),
|
|
22
26
|
key: tool.schema.string().optional().describe('应用key,例如 list-repos'),
|
|
@@ -42,7 +46,9 @@ export const createRouterAgentPluginFn = (opts?: {
|
|
|
42
46
|
query?: string,
|
|
43
47
|
hooks?: (plugin: PluginInput) => Promise<Hooks>
|
|
44
48
|
}) => {
|
|
49
|
+
new Promise(resolve => setTimeout(resolve, 100)) // 等待路由加载
|
|
45
50
|
let router = opts?.router
|
|
51
|
+
|
|
46
52
|
if (!router) {
|
|
47
53
|
const app = useContextKey<App>('app')
|
|
48
54
|
router = app
|
|
@@ -59,13 +65,15 @@ export const createRouterAgentPluginFn = (opts?: {
|
|
|
59
65
|
const _routes = filter(router.routes, opts?.query || '')
|
|
60
66
|
const routes = _routes.filter(r => {
|
|
61
67
|
const metadata = r.metadata as Skill
|
|
68
|
+
if (metadata && metadata.skill && metadata.summary) {
|
|
69
|
+
return true
|
|
70
|
+
}
|
|
62
71
|
if (metadata && metadata.tags && metadata.tags.includes('opencode')) {
|
|
63
72
|
return !!metadata.skill
|
|
64
73
|
}
|
|
65
74
|
return false
|
|
66
75
|
});
|
|
67
|
-
|
|
68
|
-
// opencode run "查看系统信息"
|
|
76
|
+
// opencode run "使用技能查看系统信息"
|
|
69
77
|
const AgentPlugin: Plugin = async (pluginInput) => {
|
|
70
78
|
useContextKey<PluginInput>('plugin-input', () => pluginInput, true)
|
|
71
79
|
const hooks = opts?.hooks ? await opts.hooks(pluginInput) : {}
|
|
@@ -74,10 +82,11 @@ export const createRouterAgentPluginFn = (opts?: {
|
|
|
74
82
|
'tool': {
|
|
75
83
|
...routes.reduce((acc, route) => {
|
|
76
84
|
const metadata = route.metadata as Skill
|
|
85
|
+
let args = extractArgs(metadata?.args)
|
|
77
86
|
acc[metadata.skill!] = {
|
|
78
87
|
name: metadata.title || metadata.skill,
|
|
79
88
|
description: metadata.summary || '',
|
|
80
|
-
args:
|
|
89
|
+
args: args,
|
|
81
90
|
async execute(args: Record<string, any>) {
|
|
82
91
|
const res = await router.run({
|
|
83
92
|
path: route.path,
|
|
@@ -117,4 +126,17 @@ export const createRouterAgentPluginFn = (opts?: {
|
|
|
117
126
|
|
|
118
127
|
export const usePluginInput = (): PluginInput => {
|
|
119
128
|
return useContextKey<PluginInput>('plugin-input')
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* 如果args是z.object类型,拆分第一个Object的属性,比如z.object({ name: z.string(), age: z.number() }),拆分成{name: z.string(), age: z.number()}
|
|
133
|
+
* 如果args是普通对象,直接返回
|
|
134
|
+
* @param args
|
|
135
|
+
* @returns
|
|
136
|
+
*/
|
|
137
|
+
export const extractArgs = (args: any) => {
|
|
138
|
+
if (args && typeof args === 'object' && typeof args.shape === 'object') {
|
|
139
|
+
return args.shape
|
|
140
|
+
}
|
|
141
|
+
return args || {}
|
|
120
142
|
}
|
package/src/route.ts
CHANGED
|
@@ -97,6 +97,7 @@ export type Skill<T = SimpleObject> = {
|
|
|
97
97
|
skill: string;
|
|
98
98
|
title: string;
|
|
99
99
|
summary?: string;
|
|
100
|
+
tags?: string[];
|
|
100
101
|
args?: {
|
|
101
102
|
[key: string]: any
|
|
102
103
|
};
|
|
@@ -106,6 +107,12 @@ export const tool = {
|
|
|
106
107
|
}
|
|
107
108
|
/** */
|
|
108
109
|
export const createSkill = <T = SimpleObject>(skill: Skill<T>): Skill<T> => {
|
|
110
|
+
if (skill.tags) {
|
|
111
|
+
const hasOpencode = skill.tags.includes('opencode');
|
|
112
|
+
if (!hasOpencode) {
|
|
113
|
+
skill.tags.push('opencode');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
109
116
|
return {
|
|
110
117
|
args: {},
|
|
111
118
|
...skill
|
|
@@ -130,7 +137,6 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
|
|
|
130
137
|
metadata?: T;
|
|
131
138
|
middleware?: RouteMiddleware[]; // middleware
|
|
132
139
|
type? = 'route';
|
|
133
|
-
data?: any;
|
|
134
140
|
/**
|
|
135
141
|
* 是否开启debug,开启后会打印错误信息
|
|
136
142
|
*/
|
|
@@ -234,19 +240,25 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
|
|
|
234
240
|
addTo(router: QueryRouter | { add: (route: Route) => void;[key: string]: any }, opts?: AddOpts) {
|
|
235
241
|
router.add(this, opts);
|
|
236
242
|
}
|
|
237
|
-
setData(data: any) {
|
|
238
|
-
this.data = data;
|
|
239
|
-
return this;
|
|
240
|
-
}
|
|
241
243
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
242
244
|
throw(...args: any[]) {
|
|
243
245
|
throw new CustomError(...args);
|
|
244
246
|
}
|
|
245
247
|
}
|
|
248
|
+
export const extractArgs = (args: any) => {
|
|
249
|
+
if (args && typeof args === 'object' && typeof args.shape === 'object') {
|
|
250
|
+
return args.shape as z.ZodRawShape;
|
|
251
|
+
}
|
|
252
|
+
return args || {};
|
|
253
|
+
};
|
|
254
|
+
|
|
246
255
|
export const toJSONSchema = (route: RouteInfo) => {
|
|
247
256
|
const pickValues = pick(route, pickValue as any);
|
|
248
257
|
if (pickValues?.metadata?.args) {
|
|
249
|
-
|
|
258
|
+
let args = pickValues.metadata.args;
|
|
259
|
+
// 如果 args 本身是一个 zod object schema,先提取 shape
|
|
260
|
+
args = extractArgs(args);
|
|
261
|
+
|
|
250
262
|
const keys = Object.keys(args);
|
|
251
263
|
const newArgs: { [key: string]: any } = {};
|
|
252
264
|
for (let key of keys) {
|
|
@@ -265,6 +277,11 @@ export const toJSONSchema = (route: RouteInfo) => {
|
|
|
265
277
|
export const fromJSONSchema = (route: RouteInfo): RouteInfo => {
|
|
266
278
|
const args = route?.metadata?.args;
|
|
267
279
|
if (!args) return route;
|
|
280
|
+
if (args["$schema"] || (args.type === 'object' && args.properties && typeof args.properties === 'object')) {
|
|
281
|
+
// 可能是整个schema
|
|
282
|
+
route.metadata.args = z.fromJSONSchema(args);
|
|
283
|
+
return route;
|
|
284
|
+
}
|
|
268
285
|
const keys = Object.keys(args);
|
|
269
286
|
const newArgs: { [key: string]: any } = {};
|
|
270
287
|
for (let key of keys) {
|