@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.
@@ -11,6 +11,7 @@ import './share/index.ts';
11
11
  import './cnb-manager/index.ts';
12
12
  import './build/index.ts';
13
13
  import './chat/chat.ts';
14
+ import './missions/index.ts';
14
15
 
15
16
  /**
16
17
  * 验证上下文中的 App ID 是否与指定的 App ID 匹配
@@ -0,0 +1 @@
1
+ import './list.ts'
@@ -0,0 +1,39 @@
1
+ import z from 'zod';
2
+ import { app, cnbManager } from '../../app.ts';
3
+
4
+ app.route({
5
+ path: 'cnb',
6
+ key: 'missions-list',
7
+ description: '查询missions列表',
8
+ metadata: {
9
+ args: {
10
+ repo: z.string().optional().describe('missions所在的仓库,例如 kevisual/projects'),
11
+ selector: z.array(z.any()).optional().describe('查询条件,例如 [{field: "resource_type", operator: "contains", value: ["issues"]},…]'),
12
+ }
13
+ }
14
+ }).define(async (ctx) => {
15
+ const cnb = await cnbManager.getContext(ctx);
16
+ const repo = ctx.query?.repo || 'kevisual/projects';
17
+ const res = await cnb.mission.queryResources(repo, ctx.query?.selector || [
18
+ {
19
+ "field": "resource_type",
20
+ "operator": "contains",
21
+ "value": [
22
+ "issues"
23
+ ]
24
+ },
25
+ {
26
+ "field": "state",
27
+ "operator": "not_equals",
28
+ "value": [
29
+ "closed"
30
+ ]
31
+ },
32
+ {
33
+ "field": "label",
34
+ "operator": "contains",
35
+ "value": ["AICoding"]
36
+ }
37
+ ])
38
+ ctx.forward(res);
39
+ }).addTo(app);
@@ -1,2 +1,3 @@
1
1
  import './list.ts'
2
- import './repo.ts'
2
+ import './repo.ts'
3
+ import './repo-label.ts'
@@ -180,3 +180,31 @@ app.route({
180
180
  ctx.forward(res);
181
181
  }).addTo(app);
182
182
 
183
+ app.route({
184
+ path: 'cnb',
185
+ key: 'update-repo-visibility',
186
+ description: '更新代码仓库的可见性, 参数name, visibility',
187
+ middleware: ['auth'],
188
+ metadata: {
189
+ args: {
190
+ name: tool.schema.string().describe('代码仓库名称'),
191
+ visibility: tool.schema.string().describe('代码仓库可见性, public 或 private 或 protected'),
192
+ },
193
+ }
194
+ }).define(async (ctx) => {
195
+ const cnb = await cnbManager.getContext(ctx);
196
+ const name = ctx.query?.name;
197
+ const visibility = ctx.query?.visibility;
198
+
199
+ if (!name) {
200
+ ctx.throw(400, '缺少参数 name');
201
+ }
202
+ if (!visibility) {
203
+ ctx.throw(400, '缺少参数 visibility');
204
+ }
205
+ const res = await cnb.post({
206
+ url: `/${name}/-/settings/set_visibility`,
207
+ data: { visibility }
208
+ })
209
+ ctx.forward(res);
210
+ }).addTo(app);
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.3/node_modules/@kevisual/router/dist/router.js
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.7/node_modules/@kevisual/remote-app/dist/app.js
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 || "https://kevisual.cn/ws/proxy";
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.3/node_modules/@kevisual/router/src/commander.ts
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.route({
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 });