@kevisual/cnb 0.0.53 → 0.0.54
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/index.ts +1 -0
- package/agent/routes/missions/index.ts +1 -0
- package/agent/routes/missions/list.ts +39 -0
- package/agent/routes/repo/index.ts +2 -1
- package/agent/routes/repo/repo.ts +28 -0
- package/dist/cli.js +335 -44
- package/dist/npc.js +335 -44
- package/dist/opencode.js +256 -3
- package/dist/routes.d.ts +94 -0
- package/dist/routes.js +255 -2
- package/package.json +1 -1
- package/src/mission/index.ts +10 -0
- package/src/mission/modules/fields.ts +164 -0
- package/src/mission/modules/resources.ts +41 -0
package/dist/npc.js
CHANGED
|
@@ -4432,7 +4432,7 @@ var require_commander = __commonJS((exports) => {
|
|
|
4432
4432
|
exports.InvalidOptionArgumentError = InvalidArgumentError3;
|
|
4433
4433
|
});
|
|
4434
4434
|
|
|
4435
|
-
// ../../node_modules/.pnpm/@kevisual+router@0.1.
|
|
4435
|
+
// ../../node_modules/.pnpm/@kevisual+router@0.1.6/node_modules/@kevisual/router/dist/router.js
|
|
4436
4436
|
import { createRequire as createRequire2 } from "node:module";
|
|
4437
4437
|
import { webcrypto as crypto } from "node:crypto";
|
|
4438
4438
|
import url2 from "node:url";
|
|
@@ -21947,7 +21947,7 @@ class QueryRouter {
|
|
|
21947
21947
|
console.error("=====debug====:", e);
|
|
21948
21948
|
console.error("=====debug====:[path:key]:", `${route.path}-${route.key}`);
|
|
21949
21949
|
}
|
|
21950
|
-
if (e instanceof CustomError) {
|
|
21950
|
+
if (e instanceof CustomError || e?.code) {
|
|
21951
21951
|
ctx.code = e.code;
|
|
21952
21952
|
ctx.message = e.message;
|
|
21953
21953
|
} else {
|
|
@@ -22210,6 +22210,39 @@ class QueryRouterServer extends QueryRouter {
|
|
|
22210
22210
|
const { path, key, id } = api2;
|
|
22211
22211
|
return this.run({ path, key, id, payload }, ctx);
|
|
22212
22212
|
}
|
|
22213
|
+
async createAuth(fun) {
|
|
22214
|
+
this.route({
|
|
22215
|
+
path: "auth",
|
|
22216
|
+
key: "auth",
|
|
22217
|
+
id: "auth",
|
|
22218
|
+
description: "token验证"
|
|
22219
|
+
}).define(async (ctx) => {
|
|
22220
|
+
if (fun) {
|
|
22221
|
+
await fun(ctx, "auth");
|
|
22222
|
+
}
|
|
22223
|
+
}).addTo(this, { overwrite: false });
|
|
22224
|
+
this.route({
|
|
22225
|
+
path: "auth-admin",
|
|
22226
|
+
key: "auth-admin",
|
|
22227
|
+
id: "auth-admin",
|
|
22228
|
+
description: "admin token验证",
|
|
22229
|
+
middleware: ["auth"]
|
|
22230
|
+
}).define(async (ctx) => {
|
|
22231
|
+
if (fun) {
|
|
22232
|
+
await fun(ctx, "auth-admin");
|
|
22233
|
+
}
|
|
22234
|
+
}).addTo(this, { overwrite: false });
|
|
22235
|
+
this.route({
|
|
22236
|
+
path: "auth-can",
|
|
22237
|
+
key: "auth-can",
|
|
22238
|
+
id: "auth-can",
|
|
22239
|
+
description: "权限验证"
|
|
22240
|
+
}).define(async (ctx) => {
|
|
22241
|
+
if (fun) {
|
|
22242
|
+
await fun(ctx, "auth-can");
|
|
22243
|
+
}
|
|
22244
|
+
}).addTo(this, { overwrite: false });
|
|
22245
|
+
}
|
|
22213
22246
|
}
|
|
22214
22247
|
var isNode2 = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
22215
22248
|
var isBrowser2 = typeof window !== "undefined" && typeof document !== "undefined" && typeof document.createElement === "function";
|
|
@@ -25054,6 +25087,22 @@ class Issue extends CNBCore {
|
|
|
25054
25087
|
}
|
|
25055
25088
|
}
|
|
25056
25089
|
|
|
25090
|
+
// src/mission/modules/resources.ts
|
|
25091
|
+
var queryResources = async (cnb, opts) => {
|
|
25092
|
+
const url3 = `${cnb.hackURL}/${opts?.repo || "kevisual/projects"}/-/mission-resource/resources`;
|
|
25093
|
+
return cnb.post({
|
|
25094
|
+
url: url3,
|
|
25095
|
+
data: {
|
|
25096
|
+
selectors: opts?.selectors,
|
|
25097
|
+
slugName: opts?.repo
|
|
25098
|
+
},
|
|
25099
|
+
headers: {
|
|
25100
|
+
Accept: "application/vnd.cnb.web+json"
|
|
25101
|
+
},
|
|
25102
|
+
useCookie: true
|
|
25103
|
+
});
|
|
25104
|
+
};
|
|
25105
|
+
|
|
25057
25106
|
// src/mission/index.ts
|
|
25058
25107
|
class Mission extends CNBCore {
|
|
25059
25108
|
constructor(options) {
|
|
@@ -25116,6 +25165,9 @@ class Mission extends CNBCore {
|
|
|
25116
25165
|
params: { visibility }
|
|
25117
25166
|
});
|
|
25118
25167
|
}
|
|
25168
|
+
queryResources(repo, selectors) {
|
|
25169
|
+
return queryResources(this, { repo, selectors });
|
|
25170
|
+
}
|
|
25119
25171
|
}
|
|
25120
25172
|
|
|
25121
25173
|
// src/ai/index.ts
|
|
@@ -46978,6 +47030,169 @@ app.route({
|
|
|
46978
47030
|
const res = await cnb.repo.updateRepoInfo(name15, { description, license, site, topics });
|
|
46979
47031
|
ctx.forward(res);
|
|
46980
47032
|
}).addTo(app);
|
|
47033
|
+
app.route({
|
|
47034
|
+
path: "cnb",
|
|
47035
|
+
key: "update-repo-visibility",
|
|
47036
|
+
description: "更新代码仓库的可见性, 参数name, visibility",
|
|
47037
|
+
middleware: ["auth"],
|
|
47038
|
+
metadata: {
|
|
47039
|
+
args: {
|
|
47040
|
+
name: tool.schema.string().describe("代码仓库名称"),
|
|
47041
|
+
visibility: tool.schema.string().describe("代码仓库可见性, public 或 private 或 protected")
|
|
47042
|
+
}
|
|
47043
|
+
}
|
|
47044
|
+
}).define(async (ctx) => {
|
|
47045
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47046
|
+
const name15 = ctx.query?.name;
|
|
47047
|
+
const visibility = ctx.query?.visibility;
|
|
47048
|
+
if (!name15) {
|
|
47049
|
+
ctx.throw(400, "缺少参数 name");
|
|
47050
|
+
}
|
|
47051
|
+
if (!visibility) {
|
|
47052
|
+
ctx.throw(400, "缺少参数 visibility");
|
|
47053
|
+
}
|
|
47054
|
+
const res = await cnb.post({
|
|
47055
|
+
url: `/${name15}/-/settings/set_visibility`,
|
|
47056
|
+
data: { visibility }
|
|
47057
|
+
});
|
|
47058
|
+
ctx.forward(res);
|
|
47059
|
+
}).addTo(app);
|
|
47060
|
+
|
|
47061
|
+
// agent/routes/repo/repo-label.ts
|
|
47062
|
+
app.route({
|
|
47063
|
+
path: "cnb",
|
|
47064
|
+
key: "list-repo-labels",
|
|
47065
|
+
description: "查询仓库的标签列表",
|
|
47066
|
+
middleware: ["auth"],
|
|
47067
|
+
metadata: {
|
|
47068
|
+
tags: ["opencode"],
|
|
47069
|
+
...createSkill({
|
|
47070
|
+
skill: "list-repo-labels",
|
|
47071
|
+
title: "查询仓库标签列表",
|
|
47072
|
+
summary: "查询仓库的标签列表",
|
|
47073
|
+
args: {
|
|
47074
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47075
|
+
page: tool.schema.number().optional().describe("分页页码,默认 1"),
|
|
47076
|
+
pageSize: tool.schema.number().optional().describe("分页每页大小,默认 30"),
|
|
47077
|
+
keyword: tool.schema.string().optional().describe("标签搜索关键词")
|
|
47078
|
+
}
|
|
47079
|
+
})
|
|
47080
|
+
}
|
|
47081
|
+
}).define(async (ctx) => {
|
|
47082
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47083
|
+
const repo2 = ctx.query?.repo;
|
|
47084
|
+
const page = ctx.query?.page;
|
|
47085
|
+
const pageSize = ctx.query?.pageSize;
|
|
47086
|
+
const keyword = ctx.query?.keyword;
|
|
47087
|
+
if (!repo2) {
|
|
47088
|
+
ctx.throw(400, "缺少参数 repo");
|
|
47089
|
+
}
|
|
47090
|
+
const res = await cnb.labels.repoLabel.list(repo2, {
|
|
47091
|
+
page,
|
|
47092
|
+
page_size: pageSize,
|
|
47093
|
+
keyword
|
|
47094
|
+
});
|
|
47095
|
+
ctx.forward(res);
|
|
47096
|
+
}).addTo(app);
|
|
47097
|
+
app.route({
|
|
47098
|
+
path: "cnb",
|
|
47099
|
+
key: "create-repo-label",
|
|
47100
|
+
description: "创建仓库标签",
|
|
47101
|
+
middleware: ["auth"],
|
|
47102
|
+
metadata: {
|
|
47103
|
+
tags: ["opencode"],
|
|
47104
|
+
...createSkill({
|
|
47105
|
+
skill: "create-repo-label",
|
|
47106
|
+
title: "创建仓库标签",
|
|
47107
|
+
summary: "创建一个仓库标签",
|
|
47108
|
+
args: {
|
|
47109
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47110
|
+
name: tool.schema.string().describe("标签名称"),
|
|
47111
|
+
color: tool.schema.string().describe("标签颜色,十六进制颜色码,不含 # 前缀"),
|
|
47112
|
+
description: tool.schema.string().optional().describe("标签描述")
|
|
47113
|
+
}
|
|
47114
|
+
})
|
|
47115
|
+
}
|
|
47116
|
+
}).define(async (ctx) => {
|
|
47117
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47118
|
+
const repo2 = ctx.query?.repo;
|
|
47119
|
+
const name15 = ctx.query?.name;
|
|
47120
|
+
const color = ctx.query?.color;
|
|
47121
|
+
const description = ctx.query?.description;
|
|
47122
|
+
if (!repo2 || !name15 || !color) {
|
|
47123
|
+
ctx.throw(400, "缺少参数 repo, name 或 color");
|
|
47124
|
+
}
|
|
47125
|
+
const res = await cnb.labels.repoLabel.create(repo2, {
|
|
47126
|
+
name: name15,
|
|
47127
|
+
color,
|
|
47128
|
+
description
|
|
47129
|
+
});
|
|
47130
|
+
ctx.forward(res);
|
|
47131
|
+
}).addTo(app);
|
|
47132
|
+
app.route({
|
|
47133
|
+
path: "cnb",
|
|
47134
|
+
key: "update-repo-label",
|
|
47135
|
+
description: "更新仓库标签",
|
|
47136
|
+
middleware: ["auth"],
|
|
47137
|
+
metadata: {
|
|
47138
|
+
tags: ["opencode"],
|
|
47139
|
+
...createSkill({
|
|
47140
|
+
skill: "update-repo-label",
|
|
47141
|
+
title: "更新仓库标签",
|
|
47142
|
+
summary: "更新仓库标签信息",
|
|
47143
|
+
args: {
|
|
47144
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47145
|
+
name: tool.schema.string().describe("标签名称"),
|
|
47146
|
+
color: tool.schema.string().optional().describe("标签颜色,十六进制颜色码,不含 # 前缀"),
|
|
47147
|
+
description: tool.schema.string().optional().describe("标签描述"),
|
|
47148
|
+
newName: tool.schema.string().optional().describe("新标签名称")
|
|
47149
|
+
}
|
|
47150
|
+
})
|
|
47151
|
+
}
|
|
47152
|
+
}).define(async (ctx) => {
|
|
47153
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47154
|
+
const repo2 = ctx.query?.repo;
|
|
47155
|
+
const name15 = ctx.query?.name;
|
|
47156
|
+
const color = ctx.query?.color;
|
|
47157
|
+
const description = ctx.query?.description;
|
|
47158
|
+
const newName = ctx.query?.newName;
|
|
47159
|
+
if (!repo2 || !name15) {
|
|
47160
|
+
ctx.throw(400, "缺少参数 repo 或 name");
|
|
47161
|
+
}
|
|
47162
|
+
const res = await cnb.labels.repoLabel.update(repo2, name15, {
|
|
47163
|
+
color,
|
|
47164
|
+
description,
|
|
47165
|
+
new_name: newName
|
|
47166
|
+
});
|
|
47167
|
+
ctx.forward(res);
|
|
47168
|
+
}).addTo(app);
|
|
47169
|
+
app.route({
|
|
47170
|
+
path: "cnb",
|
|
47171
|
+
key: "delete-repo-label",
|
|
47172
|
+
description: "删除仓库标签",
|
|
47173
|
+
middleware: ["auth"],
|
|
47174
|
+
metadata: {
|
|
47175
|
+
tags: ["opencode"],
|
|
47176
|
+
...createSkill({
|
|
47177
|
+
skill: "delete-repo-label",
|
|
47178
|
+
title: "删除仓库标签",
|
|
47179
|
+
summary: "删除指定的仓库标签",
|
|
47180
|
+
args: {
|
|
47181
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47182
|
+
name: tool.schema.string().describe("标签名称")
|
|
47183
|
+
}
|
|
47184
|
+
})
|
|
47185
|
+
}
|
|
47186
|
+
}).define(async (ctx) => {
|
|
47187
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47188
|
+
const repo2 = ctx.query?.repo;
|
|
47189
|
+
const name15 = ctx.query?.name;
|
|
47190
|
+
if (!repo2 || !name15) {
|
|
47191
|
+
ctx.throw(400, "缺少参数 repo 或 name");
|
|
47192
|
+
}
|
|
47193
|
+
const res = await cnb.labels.repoLabel.remove(repo2, name15);
|
|
47194
|
+
ctx.forward(res);
|
|
47195
|
+
}).addTo(app);
|
|
46981
47196
|
|
|
46982
47197
|
// agent/routes/workspace/skills.ts
|
|
46983
47198
|
app.route({
|
|
@@ -55194,6 +55409,44 @@ app.route({
|
|
|
55194
55409
|
ctx.body = result;
|
|
55195
55410
|
}).addTo(app);
|
|
55196
55411
|
|
|
55412
|
+
// agent/routes/missions/list.ts
|
|
55413
|
+
app.route({
|
|
55414
|
+
path: "cnb",
|
|
55415
|
+
key: "missions-list",
|
|
55416
|
+
description: "查询missions列表",
|
|
55417
|
+
metadata: {
|
|
55418
|
+
args: {
|
|
55419
|
+
repo: zod_default.string().optional().describe("missions所在的仓库,例如 kevisual/projects"),
|
|
55420
|
+
selector: zod_default.array(zod_default.any()).optional().describe('查询条件,例如 [{field: "resource_type", operator: "contains", value: ["issues"]},…]')
|
|
55421
|
+
}
|
|
55422
|
+
}
|
|
55423
|
+
}).define(async (ctx) => {
|
|
55424
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
55425
|
+
const repo2 = ctx.query?.repo || "kevisual/projects";
|
|
55426
|
+
const res = await cnb.mission.queryResources(repo2, ctx.query?.selector || [
|
|
55427
|
+
{
|
|
55428
|
+
field: "resource_type",
|
|
55429
|
+
operator: "contains",
|
|
55430
|
+
value: [
|
|
55431
|
+
"issues"
|
|
55432
|
+
]
|
|
55433
|
+
},
|
|
55434
|
+
{
|
|
55435
|
+
field: "state",
|
|
55436
|
+
operator: "not_equals",
|
|
55437
|
+
value: [
|
|
55438
|
+
"closed"
|
|
55439
|
+
]
|
|
55440
|
+
},
|
|
55441
|
+
{
|
|
55442
|
+
field: "label",
|
|
55443
|
+
operator: "contains",
|
|
55444
|
+
value: ["AICoding"]
|
|
55445
|
+
}
|
|
55446
|
+
]);
|
|
55447
|
+
ctx.forward(res);
|
|
55448
|
+
}).addTo(app);
|
|
55449
|
+
|
|
55197
55450
|
// agent/routes/index.ts
|
|
55198
55451
|
var checkAppId = (ctx, appId) => {
|
|
55199
55452
|
const _appId = ctx?.app?.appId;
|
|
@@ -55245,7 +55498,7 @@ var {
|
|
|
55245
55498
|
Help
|
|
55246
55499
|
} = import__3.default;
|
|
55247
55500
|
|
|
55248
|
-
// ../../node_modules/.pnpm/@kevisual+remote-app@0.0.
|
|
55501
|
+
// ../../node_modules/.pnpm/@kevisual+remote-app@0.0.6/node_modules/@kevisual/remote-app/dist/app.js
|
|
55249
55502
|
var __create4 = Object.create;
|
|
55250
55503
|
var __getProtoOf4 = Object.getPrototypeOf;
|
|
55251
55504
|
var __defProp5 = Object.defineProperty;
|
|
@@ -55460,12 +55713,10 @@ class RemoteApp {
|
|
|
55460
55713
|
reconnectAttempts = 0;
|
|
55461
55714
|
reconnectTimer = null;
|
|
55462
55715
|
isManuallyClosed = false;
|
|
55463
|
-
isInitializing = false;
|
|
55464
|
-
initId = 0;
|
|
55465
55716
|
constructor(opts) {
|
|
55466
55717
|
this.mainApp = opts?.app;
|
|
55467
55718
|
const token2 = opts.token;
|
|
55468
|
-
const url4 = opts.url
|
|
55719
|
+
const url4 = opts.url;
|
|
55469
55720
|
const id = opts.id;
|
|
55470
55721
|
const username = opts.username;
|
|
55471
55722
|
this.username = username;
|
|
@@ -55531,17 +55782,10 @@ class RemoteApp {
|
|
|
55531
55782
|
return wsURL;
|
|
55532
55783
|
}
|
|
55533
55784
|
async init() {
|
|
55534
|
-
if (this.isInitializing) {
|
|
55535
|
-
return;
|
|
55536
|
-
}
|
|
55537
|
-
this.isInitializing = true;
|
|
55538
|
-
const currentInitId = ++this.initId;
|
|
55539
55785
|
if (!this.url) {
|
|
55540
|
-
this.isInitializing = false;
|
|
55541
55786
|
throw new Error("No url provided for remote app");
|
|
55542
55787
|
}
|
|
55543
55788
|
if (!this.id) {
|
|
55544
|
-
this.isInitializing = false;
|
|
55545
55789
|
throw new Error("No id provided for remote app");
|
|
55546
55790
|
}
|
|
55547
55791
|
this.isError = false;
|
|
@@ -55551,20 +55795,11 @@ class RemoteApp {
|
|
|
55551
55795
|
const ws = new WebSocket(this.getWsURL(this.url));
|
|
55552
55796
|
const that = this;
|
|
55553
55797
|
ws.onopen = function() {
|
|
55554
|
-
if (currentInitId !== that.initId) {
|
|
55555
|
-
ws.close();
|
|
55556
|
-
return;
|
|
55557
|
-
}
|
|
55558
55798
|
that.isConnected = true;
|
|
55559
|
-
that.isInitializing = false;
|
|
55560
55799
|
that.onOpen();
|
|
55561
55800
|
console.log("[remote-app] WebSocket connection opened");
|
|
55562
55801
|
};
|
|
55563
55802
|
ws.onclose = function() {
|
|
55564
|
-
if (currentInitId !== that.initId) {
|
|
55565
|
-
return;
|
|
55566
|
-
}
|
|
55567
|
-
that.isInitializing = false;
|
|
55568
55803
|
that.isConnected = false;
|
|
55569
55804
|
that.onClose();
|
|
55570
55805
|
};
|
|
@@ -55572,10 +55807,6 @@ class RemoteApp {
|
|
|
55572
55807
|
that.onMessage(event.data);
|
|
55573
55808
|
};
|
|
55574
55809
|
ws.onerror = function(error49) {
|
|
55575
|
-
if (currentInitId !== that.initId) {
|
|
55576
|
-
return;
|
|
55577
|
-
}
|
|
55578
|
-
that.isInitializing = false;
|
|
55579
55810
|
that.onError(error49);
|
|
55580
55811
|
};
|
|
55581
55812
|
this.ws = ws;
|
|
@@ -55729,7 +55960,7 @@ class RemoteApp {
|
|
|
55729
55960
|
}
|
|
55730
55961
|
}
|
|
55731
55962
|
|
|
55732
|
-
// ../../node_modules/.pnpm/@kevisual+router@0.1.
|
|
55963
|
+
// ../../node_modules/.pnpm/@kevisual+router@0.1.6/node_modules/@kevisual/router/src/commander.ts
|
|
55733
55964
|
var groupByPath = (routes) => {
|
|
55734
55965
|
return routes.reduce((acc, route) => {
|
|
55735
55966
|
const path3 = route.path || "default";
|
|
@@ -55849,23 +56080,7 @@ var parse8 = async (opts) => {
|
|
|
55849
56080
|
_program.version(version3);
|
|
55850
56081
|
}
|
|
55851
56082
|
app3.createRouteList();
|
|
55852
|
-
app3
|
|
55853
|
-
path: "cli",
|
|
55854
|
-
key: "list"
|
|
55855
|
-
}).define(async () => {
|
|
55856
|
-
const routes = app3.routes.map((route) => {
|
|
55857
|
-
return {
|
|
55858
|
-
path: route.path,
|
|
55859
|
-
key: route.key,
|
|
55860
|
-
description: route?.metadata?.summary || route.description || ""
|
|
55861
|
-
};
|
|
55862
|
-
});
|
|
55863
|
-
const table = routes.map((route) => {
|
|
55864
|
-
return `${route.path} ${route.key} - ${route.description}`;
|
|
55865
|
-
}).join(`
|
|
55866
|
-
`);
|
|
55867
|
-
console.log(table);
|
|
55868
|
-
}).addTo(app3, { overwrite: false });
|
|
56083
|
+
createCliList(app3);
|
|
55869
56084
|
createCommand2({ app: app3, program: _program });
|
|
55870
56085
|
if (opts.remote) {
|
|
55871
56086
|
const { token: token2, username, id } = opts.remote;
|
|
@@ -55888,6 +56103,82 @@ var parse8 = async (opts) => {
|
|
|
55888
56103
|
}
|
|
55889
56104
|
}
|
|
55890
56105
|
};
|
|
56106
|
+
var createCliList = (app3) => {
|
|
56107
|
+
app3.route({
|
|
56108
|
+
path: "cli",
|
|
56109
|
+
key: "list",
|
|
56110
|
+
description: "列出所有可用的命令",
|
|
56111
|
+
metadata: {
|
|
56112
|
+
summary: "列出所有可用的命令",
|
|
56113
|
+
args: {
|
|
56114
|
+
q: zod_default.string().optional().describe("查询关键词,支持模糊匹配命令"),
|
|
56115
|
+
path: zod_default.string().optional().describe("按路径前缀过滤,如 user、admin"),
|
|
56116
|
+
tags: zod_default.string().optional().describe("按标签过滤,多个标签用逗号分隔"),
|
|
56117
|
+
sort: zod_default.enum(["key", "path", "name"]).optional().describe("排序方式"),
|
|
56118
|
+
limit: zod_default.number().optional().describe("限制返回数量"),
|
|
56119
|
+
offset: zod_default.number().optional().describe("偏移量,用于分页"),
|
|
56120
|
+
format: zod_default.enum(["table", "simple", "json"]).optional().describe("输出格式")
|
|
56121
|
+
}
|
|
56122
|
+
}
|
|
56123
|
+
}).define(async (ctx) => {
|
|
56124
|
+
const { q, path: pathFilter, tags, sort, limit, offset, format } = ctx.query;
|
|
56125
|
+
let routes = app3.routes.map((route) => {
|
|
56126
|
+
return {
|
|
56127
|
+
path: route.path,
|
|
56128
|
+
key: route.key,
|
|
56129
|
+
description: route?.metadata?.summary || route.description || "",
|
|
56130
|
+
tags: route?.metadata?.tags || []
|
|
56131
|
+
};
|
|
56132
|
+
});
|
|
56133
|
+
if (pathFilter) {
|
|
56134
|
+
routes = routes.filter((route) => route.path.startsWith(pathFilter));
|
|
56135
|
+
}
|
|
56136
|
+
if (tags) {
|
|
56137
|
+
const tagList = tags.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
|
|
56138
|
+
if (tagList.length > 0) {
|
|
56139
|
+
routes = routes.filter((route) => {
|
|
56140
|
+
const routeTags = Array.isArray(route.tags) ? route.tags.map((t) => String(t).toLowerCase()) : [];
|
|
56141
|
+
return tagList.some((tag) => routeTags.includes(tag));
|
|
56142
|
+
});
|
|
56143
|
+
}
|
|
56144
|
+
}
|
|
56145
|
+
if (q) {
|
|
56146
|
+
const keyword = q.toLowerCase();
|
|
56147
|
+
routes = routes.filter((route) => {
|
|
56148
|
+
return route.path.toLowerCase().includes(keyword) || route.key.toLowerCase().includes(keyword) || route.description.toLowerCase().includes(keyword);
|
|
56149
|
+
});
|
|
56150
|
+
}
|
|
56151
|
+
if (sort) {
|
|
56152
|
+
routes.sort((a, b) => {
|
|
56153
|
+
if (sort === "path")
|
|
56154
|
+
return a.path.localeCompare(b.path);
|
|
56155
|
+
if (sort === "key")
|
|
56156
|
+
return a.key.localeCompare(b.key);
|
|
56157
|
+
return a.key.localeCompare(b.key);
|
|
56158
|
+
});
|
|
56159
|
+
}
|
|
56160
|
+
const total = routes.length;
|
|
56161
|
+
const start = offset || 0;
|
|
56162
|
+
const end = limit ? start + limit : undefined;
|
|
56163
|
+
routes = routes.slice(start, end);
|
|
56164
|
+
const outputFormat = format || "table";
|
|
56165
|
+
if (outputFormat === "json") {
|
|
56166
|
+
console.log(JSON.stringify({ total, offset: start, limit, routes }, null, 2));
|
|
56167
|
+
return;
|
|
56168
|
+
}
|
|
56169
|
+
if (outputFormat === "simple") {
|
|
56170
|
+
routes.forEach((route) => {
|
|
56171
|
+
console.log(`${route.path} ${route.key}`);
|
|
56172
|
+
});
|
|
56173
|
+
return;
|
|
56174
|
+
}
|
|
56175
|
+
const table = routes.map((route) => {
|
|
56176
|
+
return `${route.path} ${route.key} - ${route.description}`;
|
|
56177
|
+
}).join(`
|
|
56178
|
+
`);
|
|
56179
|
+
console.log(table);
|
|
56180
|
+
}).addTo(app3, { overwrite: false });
|
|
56181
|
+
};
|
|
55891
56182
|
// ../../node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/object/pick.mjs
|
|
55892
56183
|
function pick4(obj, keys) {
|
|
55893
56184
|
const result = {};
|