@kevisual/cnb 0.0.53 → 0.0.55
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/npc.ts +55 -10
- package/agent/routes/index.ts +2 -0
- package/agent/routes/issues/comments.ts +2 -2
- package/agent/routes/labels/index.ts +1 -0
- package/agent/routes/labels/issue-label.ts +195 -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/list.ts +11 -4
- 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/cli.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";
|
|
@@ -25020,6 +25053,22 @@ class Issue extends CNBCore {
|
|
|
25020
25053
|
}
|
|
25021
25054
|
}
|
|
25022
25055
|
|
|
25056
|
+
// src/mission/modules/resources.ts
|
|
25057
|
+
var queryResources = async (cnb, opts) => {
|
|
25058
|
+
const url3 = `${cnb.hackURL}/${opts?.repo || "kevisual/projects"}/-/mission-resource/resources`;
|
|
25059
|
+
return cnb.post({
|
|
25060
|
+
url: url3,
|
|
25061
|
+
data: {
|
|
25062
|
+
selectors: opts?.selectors,
|
|
25063
|
+
slugName: opts?.repo
|
|
25064
|
+
},
|
|
25065
|
+
headers: {
|
|
25066
|
+
Accept: "application/vnd.cnb.web+json"
|
|
25067
|
+
},
|
|
25068
|
+
useCookie: true
|
|
25069
|
+
});
|
|
25070
|
+
};
|
|
25071
|
+
|
|
25023
25072
|
// src/mission/index.ts
|
|
25024
25073
|
class Mission extends CNBCore {
|
|
25025
25074
|
constructor(options) {
|
|
@@ -25082,6 +25131,9 @@ class Mission extends CNBCore {
|
|
|
25082
25131
|
params: { visibility }
|
|
25083
25132
|
});
|
|
25084
25133
|
}
|
|
25134
|
+
queryResources(repo, selectors) {
|
|
25135
|
+
return queryResources(this, { repo, selectors });
|
|
25136
|
+
}
|
|
25085
25137
|
}
|
|
25086
25138
|
|
|
25087
25139
|
// src/ai/index.ts
|
|
@@ -46944,6 +46996,169 @@ app.route({
|
|
|
46944
46996
|
const res = await cnb.repo.updateRepoInfo(name15, { description, license, site, topics });
|
|
46945
46997
|
ctx.forward(res);
|
|
46946
46998
|
}).addTo(app);
|
|
46999
|
+
app.route({
|
|
47000
|
+
path: "cnb",
|
|
47001
|
+
key: "update-repo-visibility",
|
|
47002
|
+
description: "更新代码仓库的可见性, 参数name, visibility",
|
|
47003
|
+
middleware: ["auth"],
|
|
47004
|
+
metadata: {
|
|
47005
|
+
args: {
|
|
47006
|
+
name: tool.schema.string().describe("代码仓库名称"),
|
|
47007
|
+
visibility: tool.schema.string().describe("代码仓库可见性, public 或 private 或 protected")
|
|
47008
|
+
}
|
|
47009
|
+
}
|
|
47010
|
+
}).define(async (ctx) => {
|
|
47011
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47012
|
+
const name15 = ctx.query?.name;
|
|
47013
|
+
const visibility = ctx.query?.visibility;
|
|
47014
|
+
if (!name15) {
|
|
47015
|
+
ctx.throw(400, "缺少参数 name");
|
|
47016
|
+
}
|
|
47017
|
+
if (!visibility) {
|
|
47018
|
+
ctx.throw(400, "缺少参数 visibility");
|
|
47019
|
+
}
|
|
47020
|
+
const res = await cnb.post({
|
|
47021
|
+
url: `/${name15}/-/settings/set_visibility`,
|
|
47022
|
+
data: { visibility }
|
|
47023
|
+
});
|
|
47024
|
+
ctx.forward(res);
|
|
47025
|
+
}).addTo(app);
|
|
47026
|
+
|
|
47027
|
+
// agent/routes/repo/repo-label.ts
|
|
47028
|
+
app.route({
|
|
47029
|
+
path: "cnb",
|
|
47030
|
+
key: "list-repo-labels",
|
|
47031
|
+
description: "查询仓库的标签列表",
|
|
47032
|
+
middleware: ["auth"],
|
|
47033
|
+
metadata: {
|
|
47034
|
+
tags: ["opencode"],
|
|
47035
|
+
...createSkill({
|
|
47036
|
+
skill: "list-repo-labels",
|
|
47037
|
+
title: "查询仓库标签列表",
|
|
47038
|
+
summary: "查询仓库的标签列表",
|
|
47039
|
+
args: {
|
|
47040
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47041
|
+
page: tool.schema.number().optional().describe("分页页码,默认 1"),
|
|
47042
|
+
pageSize: tool.schema.number().optional().describe("分页每页大小,默认 30"),
|
|
47043
|
+
keyword: tool.schema.string().optional().describe("标签搜索关键词")
|
|
47044
|
+
}
|
|
47045
|
+
})
|
|
47046
|
+
}
|
|
47047
|
+
}).define(async (ctx) => {
|
|
47048
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47049
|
+
const repo2 = ctx.query?.repo;
|
|
47050
|
+
const page = ctx.query?.page;
|
|
47051
|
+
const pageSize = ctx.query?.pageSize;
|
|
47052
|
+
const keyword = ctx.query?.keyword;
|
|
47053
|
+
if (!repo2) {
|
|
47054
|
+
ctx.throw(400, "缺少参数 repo");
|
|
47055
|
+
}
|
|
47056
|
+
const res = await cnb.labels.repoLabel.list(repo2, {
|
|
47057
|
+
page,
|
|
47058
|
+
page_size: pageSize,
|
|
47059
|
+
keyword
|
|
47060
|
+
});
|
|
47061
|
+
ctx.forward(res);
|
|
47062
|
+
}).addTo(app);
|
|
47063
|
+
app.route({
|
|
47064
|
+
path: "cnb",
|
|
47065
|
+
key: "create-repo-label",
|
|
47066
|
+
description: "创建仓库标签",
|
|
47067
|
+
middleware: ["auth"],
|
|
47068
|
+
metadata: {
|
|
47069
|
+
tags: ["opencode"],
|
|
47070
|
+
...createSkill({
|
|
47071
|
+
skill: "create-repo-label",
|
|
47072
|
+
title: "创建仓库标签",
|
|
47073
|
+
summary: "创建一个仓库标签",
|
|
47074
|
+
args: {
|
|
47075
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47076
|
+
name: tool.schema.string().describe("标签名称"),
|
|
47077
|
+
color: tool.schema.string().describe("标签颜色,十六进制颜色码,不含 # 前缀"),
|
|
47078
|
+
description: tool.schema.string().optional().describe("标签描述")
|
|
47079
|
+
}
|
|
47080
|
+
})
|
|
47081
|
+
}
|
|
47082
|
+
}).define(async (ctx) => {
|
|
47083
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47084
|
+
const repo2 = ctx.query?.repo;
|
|
47085
|
+
const name15 = ctx.query?.name;
|
|
47086
|
+
const color = ctx.query?.color;
|
|
47087
|
+
const description = ctx.query?.description;
|
|
47088
|
+
if (!repo2 || !name15 || !color) {
|
|
47089
|
+
ctx.throw(400, "缺少参数 repo, name 或 color");
|
|
47090
|
+
}
|
|
47091
|
+
const res = await cnb.labels.repoLabel.create(repo2, {
|
|
47092
|
+
name: name15,
|
|
47093
|
+
color,
|
|
47094
|
+
description
|
|
47095
|
+
});
|
|
47096
|
+
ctx.forward(res);
|
|
47097
|
+
}).addTo(app);
|
|
47098
|
+
app.route({
|
|
47099
|
+
path: "cnb",
|
|
47100
|
+
key: "update-repo-label",
|
|
47101
|
+
description: "更新仓库标签",
|
|
47102
|
+
middleware: ["auth"],
|
|
47103
|
+
metadata: {
|
|
47104
|
+
tags: ["opencode"],
|
|
47105
|
+
...createSkill({
|
|
47106
|
+
skill: "update-repo-label",
|
|
47107
|
+
title: "更新仓库标签",
|
|
47108
|
+
summary: "更新仓库标签信息",
|
|
47109
|
+
args: {
|
|
47110
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47111
|
+
name: tool.schema.string().describe("标签名称"),
|
|
47112
|
+
color: tool.schema.string().optional().describe("标签颜色,十六进制颜色码,不含 # 前缀"),
|
|
47113
|
+
description: tool.schema.string().optional().describe("标签描述"),
|
|
47114
|
+
newName: tool.schema.string().optional().describe("新标签名称")
|
|
47115
|
+
}
|
|
47116
|
+
})
|
|
47117
|
+
}
|
|
47118
|
+
}).define(async (ctx) => {
|
|
47119
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
47120
|
+
const repo2 = ctx.query?.repo;
|
|
47121
|
+
const name15 = ctx.query?.name;
|
|
47122
|
+
const color = ctx.query?.color;
|
|
47123
|
+
const description = ctx.query?.description;
|
|
47124
|
+
const newName = ctx.query?.newName;
|
|
47125
|
+
if (!repo2 || !name15) {
|
|
47126
|
+
ctx.throw(400, "缺少参数 repo 或 name");
|
|
47127
|
+
}
|
|
47128
|
+
const res = await cnb.labels.repoLabel.update(repo2, name15, {
|
|
47129
|
+
color,
|
|
47130
|
+
description,
|
|
47131
|
+
new_name: newName
|
|
47132
|
+
});
|
|
47133
|
+
ctx.forward(res);
|
|
47134
|
+
}).addTo(app);
|
|
47135
|
+
app.route({
|
|
47136
|
+
path: "cnb",
|
|
47137
|
+
key: "delete-repo-label",
|
|
47138
|
+
description: "删除仓库标签",
|
|
47139
|
+
middleware: ["auth"],
|
|
47140
|
+
metadata: {
|
|
47141
|
+
tags: ["opencode"],
|
|
47142
|
+
...createSkill({
|
|
47143
|
+
skill: "delete-repo-label",
|
|
47144
|
+
title: "删除仓库标签",
|
|
47145
|
+
summary: "删除指定的仓库标签",
|
|
47146
|
+
args: {
|
|
47147
|
+
repo: tool.schema.string().describe("仓库路径, 如 my-user/my-repo"),
|
|
47148
|
+
name: tool.schema.string().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
|
+
if (!repo2 || !name15) {
|
|
47157
|
+
ctx.throw(400, "缺少参数 repo 或 name");
|
|
47158
|
+
}
|
|
47159
|
+
const res = await cnb.labels.repoLabel.remove(repo2, name15);
|
|
47160
|
+
ctx.forward(res);
|
|
47161
|
+
}).addTo(app);
|
|
46947
47162
|
|
|
46948
47163
|
// agent/routes/workspace/skills.ts
|
|
46949
47164
|
app.route({
|
|
@@ -55160,6 +55375,44 @@ app.route({
|
|
|
55160
55375
|
ctx.body = result;
|
|
55161
55376
|
}).addTo(app);
|
|
55162
55377
|
|
|
55378
|
+
// agent/routes/missions/list.ts
|
|
55379
|
+
app.route({
|
|
55380
|
+
path: "cnb",
|
|
55381
|
+
key: "missions-list",
|
|
55382
|
+
description: "查询missions列表",
|
|
55383
|
+
metadata: {
|
|
55384
|
+
args: {
|
|
55385
|
+
repo: zod_default.string().optional().describe("missions所在的仓库,例如 kevisual/projects"),
|
|
55386
|
+
selector: zod_default.array(zod_default.any()).optional().describe('查询条件,例如 [{field: "resource_type", operator: "contains", value: ["issues"]},…]')
|
|
55387
|
+
}
|
|
55388
|
+
}
|
|
55389
|
+
}).define(async (ctx) => {
|
|
55390
|
+
const cnb = await cnbManager.getContext(ctx);
|
|
55391
|
+
const repo2 = ctx.query?.repo || "kevisual/projects";
|
|
55392
|
+
const res = await cnb.mission.queryResources(repo2, ctx.query?.selector || [
|
|
55393
|
+
{
|
|
55394
|
+
field: "resource_type",
|
|
55395
|
+
operator: "contains",
|
|
55396
|
+
value: [
|
|
55397
|
+
"issues"
|
|
55398
|
+
]
|
|
55399
|
+
},
|
|
55400
|
+
{
|
|
55401
|
+
field: "state",
|
|
55402
|
+
operator: "not_equals",
|
|
55403
|
+
value: [
|
|
55404
|
+
"closed"
|
|
55405
|
+
]
|
|
55406
|
+
},
|
|
55407
|
+
{
|
|
55408
|
+
field: "label",
|
|
55409
|
+
operator: "contains",
|
|
55410
|
+
value: ["AICoding"]
|
|
55411
|
+
}
|
|
55412
|
+
]);
|
|
55413
|
+
ctx.forward(res);
|
|
55414
|
+
}).addTo(app);
|
|
55415
|
+
|
|
55163
55416
|
// agent/routes/index.ts
|
|
55164
55417
|
var checkAppId = (ctx, appId) => {
|
|
55165
55418
|
const _appId = ctx?.app?.appId;
|
|
@@ -55211,7 +55464,7 @@ var {
|
|
|
55211
55464
|
Help
|
|
55212
55465
|
} = import__3.default;
|
|
55213
55466
|
|
|
55214
|
-
// ../../node_modules/.pnpm/@kevisual+remote-app@0.0.
|
|
55467
|
+
// ../../node_modules/.pnpm/@kevisual+remote-app@0.0.6/node_modules/@kevisual/remote-app/dist/app.js
|
|
55215
55468
|
var __create4 = Object.create;
|
|
55216
55469
|
var __getProtoOf4 = Object.getPrototypeOf;
|
|
55217
55470
|
var __defProp5 = Object.defineProperty;
|
|
@@ -55426,12 +55679,10 @@ class RemoteApp {
|
|
|
55426
55679
|
reconnectAttempts = 0;
|
|
55427
55680
|
reconnectTimer = null;
|
|
55428
55681
|
isManuallyClosed = false;
|
|
55429
|
-
isInitializing = false;
|
|
55430
|
-
initId = 0;
|
|
55431
55682
|
constructor(opts) {
|
|
55432
55683
|
this.mainApp = opts?.app;
|
|
55433
55684
|
const token2 = opts.token;
|
|
55434
|
-
const url4 = opts.url
|
|
55685
|
+
const url4 = opts.url;
|
|
55435
55686
|
const id = opts.id;
|
|
55436
55687
|
const username = opts.username;
|
|
55437
55688
|
this.username = username;
|
|
@@ -55497,17 +55748,10 @@ class RemoteApp {
|
|
|
55497
55748
|
return wsURL;
|
|
55498
55749
|
}
|
|
55499
55750
|
async init() {
|
|
55500
|
-
if (this.isInitializing) {
|
|
55501
|
-
return;
|
|
55502
|
-
}
|
|
55503
|
-
this.isInitializing = true;
|
|
55504
|
-
const currentInitId = ++this.initId;
|
|
55505
55751
|
if (!this.url) {
|
|
55506
|
-
this.isInitializing = false;
|
|
55507
55752
|
throw new Error("No url provided for remote app");
|
|
55508
55753
|
}
|
|
55509
55754
|
if (!this.id) {
|
|
55510
|
-
this.isInitializing = false;
|
|
55511
55755
|
throw new Error("No id provided for remote app");
|
|
55512
55756
|
}
|
|
55513
55757
|
this.isError = false;
|
|
@@ -55517,20 +55761,11 @@ class RemoteApp {
|
|
|
55517
55761
|
const ws = new WebSocket(this.getWsURL(this.url));
|
|
55518
55762
|
const that = this;
|
|
55519
55763
|
ws.onopen = function() {
|
|
55520
|
-
if (currentInitId !== that.initId) {
|
|
55521
|
-
ws.close();
|
|
55522
|
-
return;
|
|
55523
|
-
}
|
|
55524
55764
|
that.isConnected = true;
|
|
55525
|
-
that.isInitializing = false;
|
|
55526
55765
|
that.onOpen();
|
|
55527
55766
|
console.log("[remote-app] WebSocket connection opened");
|
|
55528
55767
|
};
|
|
55529
55768
|
ws.onclose = function() {
|
|
55530
|
-
if (currentInitId !== that.initId) {
|
|
55531
|
-
return;
|
|
55532
|
-
}
|
|
55533
|
-
that.isInitializing = false;
|
|
55534
55769
|
that.isConnected = false;
|
|
55535
55770
|
that.onClose();
|
|
55536
55771
|
};
|
|
@@ -55538,10 +55773,6 @@ class RemoteApp {
|
|
|
55538
55773
|
that.onMessage(event.data);
|
|
55539
55774
|
};
|
|
55540
55775
|
ws.onerror = function(error49) {
|
|
55541
|
-
if (currentInitId !== that.initId) {
|
|
55542
|
-
return;
|
|
55543
|
-
}
|
|
55544
|
-
that.isInitializing = false;
|
|
55545
55776
|
that.onError(error49);
|
|
55546
55777
|
};
|
|
55547
55778
|
this.ws = ws;
|
|
@@ -55695,7 +55926,7 @@ class RemoteApp {
|
|
|
55695
55926
|
}
|
|
55696
55927
|
}
|
|
55697
55928
|
|
|
55698
|
-
// ../../node_modules/.pnpm/@kevisual+router@0.1.
|
|
55929
|
+
// ../../node_modules/.pnpm/@kevisual+router@0.1.6/node_modules/@kevisual/router/src/commander.ts
|
|
55699
55930
|
var groupByPath = (routes) => {
|
|
55700
55931
|
return routes.reduce((acc, route) => {
|
|
55701
55932
|
const path3 = route.path || "default";
|
|
@@ -55815,23 +56046,7 @@ var parse8 = async (opts) => {
|
|
|
55815
56046
|
_program.version(version3);
|
|
55816
56047
|
}
|
|
55817
56048
|
app3.createRouteList();
|
|
55818
|
-
app3
|
|
55819
|
-
path: "cli",
|
|
55820
|
-
key: "list"
|
|
55821
|
-
}).define(async () => {
|
|
55822
|
-
const routes = app3.routes.map((route) => {
|
|
55823
|
-
return {
|
|
55824
|
-
path: route.path,
|
|
55825
|
-
key: route.key,
|
|
55826
|
-
description: route?.metadata?.summary || route.description || ""
|
|
55827
|
-
};
|
|
55828
|
-
});
|
|
55829
|
-
const table = routes.map((route) => {
|
|
55830
|
-
return `${route.path} ${route.key} - ${route.description}`;
|
|
55831
|
-
}).join(`
|
|
55832
|
-
`);
|
|
55833
|
-
console.log(table);
|
|
55834
|
-
}).addTo(app3, { overwrite: false });
|
|
56049
|
+
createCliList(app3);
|
|
55835
56050
|
createCommand2({ app: app3, program: _program });
|
|
55836
56051
|
if (opts.remote) {
|
|
55837
56052
|
const { token: token2, username, id } = opts.remote;
|
|
@@ -55854,6 +56069,82 @@ var parse8 = async (opts) => {
|
|
|
55854
56069
|
}
|
|
55855
56070
|
}
|
|
55856
56071
|
};
|
|
56072
|
+
var createCliList = (app3) => {
|
|
56073
|
+
app3.route({
|
|
56074
|
+
path: "cli",
|
|
56075
|
+
key: "list",
|
|
56076
|
+
description: "列出所有可用的命令",
|
|
56077
|
+
metadata: {
|
|
56078
|
+
summary: "列出所有可用的命令",
|
|
56079
|
+
args: {
|
|
56080
|
+
q: zod_default.string().optional().describe("查询关键词,支持模糊匹配命令"),
|
|
56081
|
+
path: zod_default.string().optional().describe("按路径前缀过滤,如 user、admin"),
|
|
56082
|
+
tags: zod_default.string().optional().describe("按标签过滤,多个标签用逗号分隔"),
|
|
56083
|
+
sort: zod_default.enum(["key", "path", "name"]).optional().describe("排序方式"),
|
|
56084
|
+
limit: zod_default.number().optional().describe("限制返回数量"),
|
|
56085
|
+
offset: zod_default.number().optional().describe("偏移量,用于分页"),
|
|
56086
|
+
format: zod_default.enum(["table", "simple", "json"]).optional().describe("输出格式")
|
|
56087
|
+
}
|
|
56088
|
+
}
|
|
56089
|
+
}).define(async (ctx) => {
|
|
56090
|
+
const { q, path: pathFilter, tags, sort, limit, offset, format } = ctx.query;
|
|
56091
|
+
let routes = app3.routes.map((route) => {
|
|
56092
|
+
return {
|
|
56093
|
+
path: route.path,
|
|
56094
|
+
key: route.key,
|
|
56095
|
+
description: route?.metadata?.summary || route.description || "",
|
|
56096
|
+
tags: route?.metadata?.tags || []
|
|
56097
|
+
};
|
|
56098
|
+
});
|
|
56099
|
+
if (pathFilter) {
|
|
56100
|
+
routes = routes.filter((route) => route.path.startsWith(pathFilter));
|
|
56101
|
+
}
|
|
56102
|
+
if (tags) {
|
|
56103
|
+
const tagList = tags.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
|
|
56104
|
+
if (tagList.length > 0) {
|
|
56105
|
+
routes = routes.filter((route) => {
|
|
56106
|
+
const routeTags = Array.isArray(route.tags) ? route.tags.map((t) => String(t).toLowerCase()) : [];
|
|
56107
|
+
return tagList.some((tag) => routeTags.includes(tag));
|
|
56108
|
+
});
|
|
56109
|
+
}
|
|
56110
|
+
}
|
|
56111
|
+
if (q) {
|
|
56112
|
+
const keyword = q.toLowerCase();
|
|
56113
|
+
routes = routes.filter((route) => {
|
|
56114
|
+
return route.path.toLowerCase().includes(keyword) || route.key.toLowerCase().includes(keyword) || route.description.toLowerCase().includes(keyword);
|
|
56115
|
+
});
|
|
56116
|
+
}
|
|
56117
|
+
if (sort) {
|
|
56118
|
+
routes.sort((a, b) => {
|
|
56119
|
+
if (sort === "path")
|
|
56120
|
+
return a.path.localeCompare(b.path);
|
|
56121
|
+
if (sort === "key")
|
|
56122
|
+
return a.key.localeCompare(b.key);
|
|
56123
|
+
return a.key.localeCompare(b.key);
|
|
56124
|
+
});
|
|
56125
|
+
}
|
|
56126
|
+
const total = routes.length;
|
|
56127
|
+
const start = offset || 0;
|
|
56128
|
+
const end = limit ? start + limit : undefined;
|
|
56129
|
+
routes = routes.slice(start, end);
|
|
56130
|
+
const outputFormat = format || "table";
|
|
56131
|
+
if (outputFormat === "json") {
|
|
56132
|
+
console.log(JSON.stringify({ total, offset: start, limit, routes }, null, 2));
|
|
56133
|
+
return;
|
|
56134
|
+
}
|
|
56135
|
+
if (outputFormat === "simple") {
|
|
56136
|
+
routes.forEach((route) => {
|
|
56137
|
+
console.log(`${route.path} ${route.key}`);
|
|
56138
|
+
});
|
|
56139
|
+
return;
|
|
56140
|
+
}
|
|
56141
|
+
const table = routes.map((route) => {
|
|
56142
|
+
return `${route.path} ${route.key} - ${route.description}`;
|
|
56143
|
+
}).join(`
|
|
56144
|
+
`);
|
|
56145
|
+
console.log(table);
|
|
56146
|
+
}).addTo(app3, { overwrite: false });
|
|
56147
|
+
};
|
|
55857
56148
|
|
|
55858
56149
|
// agent/cli.ts
|
|
55859
56150
|
await parse8({ app, description: "CNB控制台命令行工具", parse: true });
|