@meet-im/lxcli 0.0.12 → 0.0.14
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/dist/commands/generate-skills.js +5 -2
- package/dist/commands/services/kb/descriptions.js +1 -0
- package/dist/commands/services/kb/handler.js +9 -0
- package/dist/commands/services/kb/index.js +10 -0
- package/dist/commands/services/kb/params.js +3 -0
- package/dist/commands/services/kb/skill-metadata.js +1 -0
- package/dist/commands/users.js +12 -1
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.js +13 -0
- package/dist/core/error.d.ts +9 -0
- package/dist/core/error.js +1 -0
- package/package.json +1 -1
|
@@ -180,7 +180,7 @@ function renderSkillMd(method, version) {
|
|
|
180
180
|
const description = METHOD_DESCRIPTIONS[method];
|
|
181
181
|
const params = PARAM_DEFS[method] || [];
|
|
182
182
|
const metadata = METHOD_SKILL_METADATA[method];
|
|
183
|
-
const skillName = `lxcli-kb-${method}`;
|
|
183
|
+
const skillName = `lxcli-kb-${camelToKebab(method)}`;
|
|
184
184
|
const hasParams = params.length > 0;
|
|
185
185
|
// 快捷参数列表(显式配置,不从 required 自动推断)
|
|
186
186
|
const shortcutParams = METHOD_SHORTCUT_PARAMS[method] || [];
|
|
@@ -240,6 +240,9 @@ metadata:
|
|
|
240
240
|
}
|
|
241
241
|
return lines.join('\n');
|
|
242
242
|
}
|
|
243
|
+
function camelToKebab(str) {
|
|
244
|
+
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
245
|
+
}
|
|
243
246
|
async function generateServiceSkills(skillsDir, serviceName, force) {
|
|
244
247
|
// 目前只支持 kb 服务
|
|
245
248
|
if (serviceName !== 'kb') {
|
|
@@ -249,7 +252,7 @@ async function generateServiceSkills(skillsDir, serviceName, force) {
|
|
|
249
252
|
const methods = Object.keys(PARAM_DEFS);
|
|
250
253
|
const version = await readPackageVersion();
|
|
251
254
|
for (const method of methods) {
|
|
252
|
-
const skillName = `lxcli-${serviceName}-${method}`;
|
|
255
|
+
const skillName = `lxcli-${serviceName}-${camelToKebab(method)}`;
|
|
253
256
|
const skillDir = path.join(skillsDir, skillName);
|
|
254
257
|
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
255
258
|
// 检查是否已有 SKILL.md(非 --force 时跳过已有文件)
|
|
@@ -180,6 +180,14 @@ export function createKbAction(method) {
|
|
|
180
180
|
}
|
|
181
181
|
params = { project_id: projectId };
|
|
182
182
|
}
|
|
183
|
+
else if (method === 'getColumns' && options.project_id) {
|
|
184
|
+
const projectId = parseTaskId(options.project_id);
|
|
185
|
+
if (projectId === null) {
|
|
186
|
+
outputCliError('PARAM_INVALID', '--project_id must be a positive integer');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
params = { project_id: projectId };
|
|
190
|
+
}
|
|
183
191
|
else if (method === 'getAllComments' && options.task_id) {
|
|
184
192
|
const taskId = parseTaskId(options.task_id);
|
|
185
193
|
if (taskId === null) {
|
|
@@ -261,6 +269,7 @@ export function createKbAction(method) {
|
|
|
261
269
|
searchSubtasks: '--project_id, --iteration_id, --user_id, --page',
|
|
262
270
|
getAllActiveIterations: '--project_id',
|
|
263
271
|
getAllCategories: '--project_id',
|
|
272
|
+
getColumns: '--project_id',
|
|
264
273
|
getAllComments: '--task_id',
|
|
265
274
|
createComment: '--task_id, --user_id and --content',
|
|
266
275
|
downloadProjectFile: '--project_id and --file_id',
|
|
@@ -103,6 +103,15 @@ const kbService = {
|
|
|
103
103
|
.option('--user <user>', 'Specify user')
|
|
104
104
|
.option('--gateway <url>', 'Override kanboard gateway')
|
|
105
105
|
.action(createKbAction('getAllComments'));
|
|
106
|
+
// getColumns 支持快捷参数 --project_id
|
|
107
|
+
cmd
|
|
108
|
+
.command('getColumns')
|
|
109
|
+
.description(METHOD_DESCRIPTIONS.getColumns)
|
|
110
|
+
.option('--params <json>', 'JSON/JSON5 params; CLI fills jsonrpc/method/id')
|
|
111
|
+
.option('--project_id <id>', 'Project ID (shortcut)')
|
|
112
|
+
.option('--user <user>', 'Specify user')
|
|
113
|
+
.option('--gateway <url>', 'Override kanboard gateway')
|
|
114
|
+
.action(createKbAction('getColumns'));
|
|
106
115
|
// createComment 支持快捷参数 --task_id / --user_id / --content
|
|
107
116
|
cmd
|
|
108
117
|
.command('createComment')
|
|
@@ -122,6 +131,7 @@ const kbService = {
|
|
|
122
131
|
item !== 'searchSubtasks' &&
|
|
123
132
|
item !== 'getAllActiveIterations' &&
|
|
124
133
|
item !== 'getAllCategories' &&
|
|
134
|
+
item !== 'getColumns' &&
|
|
125
135
|
item !== 'getAllComments' &&
|
|
126
136
|
item !== 'createComment' &&
|
|
127
137
|
item !== 'downloadProjectFile' &&
|
|
@@ -35,6 +35,9 @@ export const PARAM_DEFS = {
|
|
|
35
35
|
getAllCategories: [
|
|
36
36
|
{ name: 'project_id', type: 'integer', required: true, description: '项目 ID' },
|
|
37
37
|
],
|
|
38
|
+
getColumns: [
|
|
39
|
+
{ name: 'project_id', type: 'integer', required: true, description: '项目 ID' },
|
|
40
|
+
],
|
|
38
41
|
getAllComments: [
|
|
39
42
|
{ name: 'task_id', type: 'integer', required: true, description: '需求/bug ID' },
|
|
40
43
|
],
|
|
@@ -5,6 +5,7 @@ export const METHOD_SHORTCUT_PARAMS = {
|
|
|
5
5
|
searchSubtasks: ['project_id', 'iteration_id', 'user_id', 'page'],
|
|
6
6
|
getAllActiveIterations: ['project_id'],
|
|
7
7
|
getAllCategories: ['project_id'],
|
|
8
|
+
getColumns: ['project_id'],
|
|
8
9
|
getAllComments: ['task_id'],
|
|
9
10
|
createComment: ['task_id', 'user_id', 'content'],
|
|
10
11
|
createProjectFile: ['file', 'project_id'],
|
package/dist/commands/users.js
CHANGED
|
@@ -138,6 +138,7 @@ export function registerUsersCommand(program) {
|
|
|
138
138
|
.description('Update user configuration (id: name or name@tenant)')
|
|
139
139
|
.option('--token <token>', 'Update authentication token')
|
|
140
140
|
.option('-e, --env <env>', `Update environment (${ENVIRONMENTS.join(', ')})`)
|
|
141
|
+
.option('--name <name>', 'Update user name (changes id to name@tenant)')
|
|
141
142
|
.action((id, options) => {
|
|
142
143
|
if (!id.includes('@')) {
|
|
143
144
|
const matches = findUsersByName(id);
|
|
@@ -164,13 +165,23 @@ export function registerUsersCommand(program) {
|
|
|
164
165
|
validEnvs: [...ENVIRONMENTS],
|
|
165
166
|
});
|
|
166
167
|
}
|
|
168
|
+
if (options.name !== undefined) {
|
|
169
|
+
if (!options.name.trim()) {
|
|
170
|
+
outputCliError('PARAM_INVALID', 'Name cannot be empty', { value: options.name });
|
|
171
|
+
}
|
|
172
|
+
if (options.name.includes('@')) {
|
|
173
|
+
outputCliError('PARAM_INVALID', 'Name cannot contain "@"', { value: options.name });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
167
176
|
const updates = {};
|
|
168
177
|
if (options.token !== undefined)
|
|
169
178
|
updates.token = options.token;
|
|
170
179
|
if (options.env !== undefined)
|
|
171
180
|
updates.env = options.env;
|
|
181
|
+
if (options.name !== undefined)
|
|
182
|
+
updates.name = options.name;
|
|
172
183
|
if (Object.keys(updates).length === 0) {
|
|
173
|
-
outputCliError('PARAM_MISSING', 'No update options provided. Use --token or --
|
|
184
|
+
outputCliError('PARAM_MISSING', 'No update options provided. Use --token, --env, or --name', {});
|
|
174
185
|
}
|
|
175
186
|
const updated = updateUser(user.id, updates);
|
|
176
187
|
outputJson({
|
package/dist/core/config.d.ts
CHANGED
package/dist/core/config.js
CHANGED
|
@@ -228,6 +228,19 @@ export function updateUser(id, updates) {
|
|
|
228
228
|
const user = config.users.find(u => u.id === id);
|
|
229
229
|
if (!user)
|
|
230
230
|
return null;
|
|
231
|
+
if (updates.name !== undefined) {
|
|
232
|
+
const newId = getUserId(updates.name, user.tenant);
|
|
233
|
+
const existing = config.users.find(u => u.id === newId);
|
|
234
|
+
if (existing) {
|
|
235
|
+
outputCliError('USER_ALREADY_EXISTS', `User "${newId}" already exists`, { id: newId });
|
|
236
|
+
}
|
|
237
|
+
const oldId = user.id;
|
|
238
|
+
user.name = updates.name;
|
|
239
|
+
user.id = newId;
|
|
240
|
+
if (config.currentUser === oldId) {
|
|
241
|
+
config.currentUser = newId;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
231
244
|
if (updates.token !== undefined) {
|
|
232
245
|
user.token = updates.token;
|
|
233
246
|
}
|
package/dist/core/error.d.ts
CHANGED
|
@@ -37,6 +37,11 @@ export declare const CLI_ERROR_CODES: {
|
|
|
37
37
|
readonly reason: "userDisabled";
|
|
38
38
|
readonly exitCode: 3;
|
|
39
39
|
};
|
|
40
|
+
readonly USER_ALREADY_EXISTS: {
|
|
41
|
+
readonly code: 20003;
|
|
42
|
+
readonly reason: "userAlreadyExists";
|
|
43
|
+
readonly exitCode: 2;
|
|
44
|
+
};
|
|
40
45
|
readonly TENANT_NOT_FOUND: {
|
|
41
46
|
readonly code: 30001;
|
|
42
47
|
readonly reason: "tenantNotFound";
|
|
@@ -94,6 +99,10 @@ export declare function getErrorMeta(key: CliErrorKey): {
|
|
|
94
99
|
readonly code: 20002;
|
|
95
100
|
readonly reason: "userDisabled";
|
|
96
101
|
readonly exitCode: 3;
|
|
102
|
+
} | {
|
|
103
|
+
readonly code: 20003;
|
|
104
|
+
readonly reason: "userAlreadyExists";
|
|
105
|
+
readonly exitCode: 2;
|
|
97
106
|
} | {
|
|
98
107
|
readonly code: 30001;
|
|
99
108
|
readonly reason: "tenantNotFound";
|
package/dist/core/error.js
CHANGED
|
@@ -18,6 +18,7 @@ export const CLI_ERROR_CODES = {
|
|
|
18
18
|
PARAM_INVALID: { code: 10002, reason: 'paramInvalid', exitCode: CLI_EXIT_CODES.PARAM },
|
|
19
19
|
USER_NOT_FOUND: { code: 20001, reason: 'userNotFound', exitCode: CLI_EXIT_CODES.NOT_FOUND },
|
|
20
20
|
USER_DISABLED: { code: 20002, reason: 'userDisabled', exitCode: CLI_EXIT_CODES.AUTH },
|
|
21
|
+
USER_ALREADY_EXISTS: { code: 20003, reason: 'userAlreadyExists', exitCode: CLI_EXIT_CODES.PARAM },
|
|
21
22
|
TENANT_NOT_FOUND: { code: 30001, reason: 'tenantNotFound', exitCode: CLI_EXIT_CODES.NOT_FOUND },
|
|
22
23
|
SERVICE_NOT_FOUND: { code: 30002, reason: 'serviceNotFound', exitCode: CLI_EXIT_CODES.NOT_FOUND },
|
|
23
24
|
CONFIG_READ_ERROR: { code: 40001, reason: 'configReadError', exitCode: CLI_EXIT_CODES.INTERNAL },
|