@siming-org/cli 0.7.3 → 0.8.0
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/index.js +455 -242
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1263,6 +1263,9 @@ function readStdinLine(stream) {
|
|
|
1263
1263
|
async function handleCreateIssue(client, input) {
|
|
1264
1264
|
return client.postJson("/api/issues", input);
|
|
1265
1265
|
}
|
|
1266
|
+
async function handleDoneIssue(client, issueId, note) {
|
|
1267
|
+
return client.postJson(`/api/issues/${issueId}/done`, note !== void 0 ? { note } : {});
|
|
1268
|
+
}
|
|
1266
1269
|
async function handleListIssues(client, filters) {
|
|
1267
1270
|
const params = new URLSearchParams();
|
|
1268
1271
|
if (filters.status) params.set("status", filters.status);
|
|
@@ -1307,17 +1310,24 @@ async function handleUpdateProject(client, id, patch) {
|
|
|
1307
1310
|
return client.putJson(`/api/projects/${encodeURIComponent(id)}`, patch);
|
|
1308
1311
|
}
|
|
1309
1312
|
var OBJECT_ID_HEX = /^[a-f0-9]{24}$/;
|
|
1310
|
-
|
|
1313
|
+
function formatCandidateHint(projects, input) {
|
|
1314
|
+
const q = input.toLowerCase();
|
|
1315
|
+
const hits = projects.filter((p) => p.key.toLowerCase().includes(q) || p.name.toLowerCase().includes(q)).slice(0, 5).map((p) => `${p.key} (${p.name})`);
|
|
1316
|
+
if (hits.length === 0) return void 0;
|
|
1317
|
+
return `\u76F8\u8FD1\u9879\u76EE\uFF1A${hits.join("\u3001")}\uFF1B\u68C0\u67E5\u62FC\u5199\uFF0C\u6216 siming project list \u67E5\u770B\u5168\u90E8\u9879\u76EE`;
|
|
1318
|
+
}
|
|
1319
|
+
async function resolveProjectId(client, input, opts) {
|
|
1311
1320
|
if (OBJECT_ID_HEX.test(input)) return { success: true, data: input };
|
|
1312
1321
|
const list = await handleListProjects(client);
|
|
1313
1322
|
if (!list.success) return list;
|
|
1314
1323
|
const hit = list.data.find((p) => p.key === input);
|
|
1315
1324
|
if (!hit) {
|
|
1325
|
+
const candidateHint = opts?.withCandidates === true ? formatCandidateHint(list.data, input) : void 0;
|
|
1316
1326
|
const error = {
|
|
1317
1327
|
message: `project "${input}" not found`,
|
|
1318
1328
|
httpStatus: 404,
|
|
1319
1329
|
bizCode: "PROJECT_NOT_FOUND",
|
|
1320
|
-
hint: `check \`siming project list\` for available keys; pass --project <key|id>`
|
|
1330
|
+
hint: candidateHint ?? `check \`siming project list\` for available keys; pass --project <key|id>`
|
|
1321
1331
|
};
|
|
1322
1332
|
return fail(error);
|
|
1323
1333
|
}
|
|
@@ -1331,6 +1341,74 @@ async function resolveProjectId(client, input) {
|
|
|
1331
1341
|
}
|
|
1332
1342
|
return { success: true, data: hit.id };
|
|
1333
1343
|
}
|
|
1344
|
+
async function findProjectDetailByKey(client, key) {
|
|
1345
|
+
const list = await handleListProjects(client);
|
|
1346
|
+
if (!list.success) return list;
|
|
1347
|
+
const hit = list.data.find((p) => p.key === key);
|
|
1348
|
+
if (hit === void 0) {
|
|
1349
|
+
return fail({
|
|
1350
|
+
message: `workspace defaultProject "${key}" not found (removed or renamed)`,
|
|
1351
|
+
httpStatus: 0,
|
|
1352
|
+
bizCode: "DEFAULT_PROJECT_INVALID",
|
|
1353
|
+
hint: DEFAULT_PROJECT_HINT
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
if (hit.id === void 0) {
|
|
1357
|
+
return fail({
|
|
1358
|
+
message: `workspace defaultProject "${key}" has no id`,
|
|
1359
|
+
httpStatus: 500,
|
|
1360
|
+
hint: "server returned a project without id; check `siming project list`"
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
return ok2({ id: hit.id, status: hit.status });
|
|
1364
|
+
}
|
|
1365
|
+
var MCP_PROJECT_HINT = "MCP \u8C03\u7528\u8BF7\u4F20 projectId \u5B57\u6BB5\uFF08\u9879\u76EE key \u6216 24-hex id \u53CC\u5F62\u6001\uFF0C\u81EA\u52A8\u5F52\u4E00\uFF09\uFF1B\u53EF\u7528 `siming project list` \u67E5\u8BE2\u53EF\u7528\u9879\u76EE";
|
|
1366
|
+
var DEFAULT_PROJECT_HINT = "siming config unset defaultProject \u540E\u91CD\u8BD5\uFF0C\u6216 siming config set defaultProject <key|id> \u91CD\u8BBE\uFF1Bsiming project list \u67E5\u770B\u53EF\u7528\u9879\u76EE";
|
|
1367
|
+
var PROJECT_REQUIRED_HINT = "\u663E\u5F0F\u4F20 --project <key|id>\uFF0C\u6216 siming config set defaultProject <key|id> \u914D\u7F6E\u9ED8\u8BA4\u9879\u76EE\uFF1Bsiming project list \u67E5\u770B\u53EF\u7528\u9879\u76EE";
|
|
1368
|
+
async function resolveScopedProject(client, explicit, tail, opts) {
|
|
1369
|
+
const value = explicit !== void 0 && explicit.trim().length > 0 ? explicit.trim() : void 0;
|
|
1370
|
+
if (value !== void 0) {
|
|
1371
|
+
const r = await resolveProjectId(client, value, { withCandidates: true });
|
|
1372
|
+
if (!r.success) {
|
|
1373
|
+
return fail(
|
|
1374
|
+
opts?.channel === "mcp" && r.error.bizCode === "PROJECT_NOT_FOUND" ? { ...r.error, hint: MCP_PROJECT_HINT } : r.error
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
return ok2({ projectId: r.data, source: "explicit" });
|
|
1378
|
+
}
|
|
1379
|
+
if (tail === "explicit-only") {
|
|
1380
|
+
return ok2({ source: "explicit" });
|
|
1381
|
+
}
|
|
1382
|
+
const wsDefault = readWorkspaceConfig()?.defaultProject;
|
|
1383
|
+
if (wsDefault !== void 0) {
|
|
1384
|
+
const detail = await findProjectDetailByKey(client, wsDefault);
|
|
1385
|
+
if (!detail.success) return detail;
|
|
1386
|
+
if (detail.data.status !== "active") {
|
|
1387
|
+
return fail({
|
|
1388
|
+
message: `workspace defaultProject "${wsDefault}" is archived`,
|
|
1389
|
+
httpStatus: 0,
|
|
1390
|
+
bizCode: "DEFAULT_PROJECT_INVALID",
|
|
1391
|
+
hint: DEFAULT_PROJECT_HINT
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
return ok2({ projectId: detail.data.id, source: "workspace-default" });
|
|
1395
|
+
}
|
|
1396
|
+
if (tail === "ws-default") {
|
|
1397
|
+
return ok2({ source: "delegated" });
|
|
1398
|
+
}
|
|
1399
|
+
const list = await handleListProjects(client);
|
|
1400
|
+
if (!list.success) return list;
|
|
1401
|
+
const instanceDefault = list.data.find((p) => p.key === "default");
|
|
1402
|
+
if (instanceDefault === void 0 || instanceDefault.id === void 0) {
|
|
1403
|
+
return fail({
|
|
1404
|
+
message: `${opts?.commandLabel ?? "this command"} needs a project: no --project given, no workspace defaultProject, and no key=default project on server`,
|
|
1405
|
+
httpStatus: 0,
|
|
1406
|
+
bizCode: "PROJECT_REQUIRED",
|
|
1407
|
+
hint: PROJECT_REQUIRED_HINT
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
return ok2({ projectId: instanceDefault.id, source: "instance-default" });
|
|
1411
|
+
}
|
|
1334
1412
|
async function resolveProjectKey(client, input) {
|
|
1335
1413
|
const list = await handleListProjects(client);
|
|
1336
1414
|
if (!list.success) return list;
|
|
@@ -1463,7 +1541,9 @@ var issueArgs = {
|
|
|
1463
1541
|
// create
|
|
1464
1542
|
title: z3.string().optional(),
|
|
1465
1543
|
description: z3.string().optional(),
|
|
1466
|
-
|
|
1544
|
+
/** create 必填(T202609200001):人类审批原话逐字(1-500 字)——per-action 必填以 ISSUE_FIELD_SPECS.create.required 为权威 */
|
|
1545
|
+
approved: z3.string().optional(),
|
|
1546
|
+
// 公共:create 缺省按工作区 defaultProject(key|id 双形态通道层归一,失效报错)/ query 过滤(空/未传不过滤)
|
|
1467
1547
|
projectId: z3.string().optional(),
|
|
1468
1548
|
// query:view 缺省 open(有效未跟进完);与 REST 词汇统一(status/taskId 指定时切对应过滤)
|
|
1469
1549
|
view: hostNeutralEnum(z3.enum(["open", "all"])).optional(),
|
|
@@ -1600,7 +1680,7 @@ var TASK_FIELD_SPECS = {
|
|
|
1600
1680
|
"archnote-add": { required: ["taskId"], optional: ["text", "textItems"] }
|
|
1601
1681
|
};
|
|
1602
1682
|
var ISSUE_FIELD_SPECS = {
|
|
1603
|
-
create: { required: ["title"], optional: ["description", "projectId"] },
|
|
1683
|
+
create: { required: ["title", "approved"], optional: ["description", "projectId"] },
|
|
1604
1684
|
query: { required: [], optional: ["view", "status", "taskId", "projectId", "page", "limit"] }
|
|
1605
1685
|
};
|
|
1606
1686
|
function createMcpServer() {
|
|
@@ -1608,7 +1688,7 @@ function createMcpServer() {
|
|
|
1608
1688
|
const client = createClient(void 0, "mcp");
|
|
1609
1689
|
server.tool(
|
|
1610
1690
|
"siming_task",
|
|
1611
|
-
"task \u8D44\u6E90\u57DF\u805A\u5408\u5DE5\u5177\uFF08\u4EFB\u52A1\u5168\u64CD\u4F5C\u7ECF\u672C\u5DE5\u5177 + action \u53C2\u6570\uFF09\u3002action \u5FC5\u586B\uFF1B\u8C03\u7528\u65B9\u5E94\u5728 fieldMask \u4E2D\u5217\u51FA\u672C\u6B21\u771F\u5B9E\u63D0\u4F9B\u7684\u53EF\u9009\u5B57\u6BB5\uFF0Cmask \u5916\u7531\u5BBF\u4E3B\u81EA\u52A8\u586B\u5145\u7684\u7A7A\u4E32\u3001\u7A7A\u6570\u7EC4\u3001false\u30010 \u5747\u5FFD\u7565\uFF0Cmask \u5185\u7A7A\u6570\u7EC4/false \u8868\u793A\u663E\u5F0F\u6E05\u7A7A\u6216\u5173\u95ED\uFF1B\u5404 action \u56FA\u5B9A\u5FC5\u586B\u5B57\u6BB5\u65E0\u9700\u5199\u5165 mask\u3002\u5176\u4F59\u53C2\u6570\u5168\u53EF\u9009\u3001\u6309 action \u8FD0\u884C\u65F6\u6821\u9A8C\u5FC5\u586B\uFF08\u7F3A\u5931\u8FD4\u56DE\u5931\u8D25\u4E09\u8981\u7D20\uFF1A\u5BF9\u8C61+\u6839\u56E0+\u4FEE\u590D\u6307\u5F15\uFF09\u3002\u5199\u64CD\u4F5C\uFF08create/doc-*/record-*/archnote-add/pause/resume/cancel\uFF09\u54CD\u5E94\u4E3A\u8F7B\u91CF\u56DE\u6267\uFF1A{taskId, updated(\u89E6\u53CA\u5B57\u6BB5\u8DEF\u5F84), entry(\u65B0\u6761\u76EE id+kind\uFF0C\u4F9B\u540E\u7EED patch \u5B9A\u4F4D), echo(\u5199\u5165\u5185\u5BB9\u56DE\u663E), updatedAt, task(\u4EFB\u52A1\u8FDB\u5EA6\u6458\u8981 progress: {completed,total})}\u2014\u2014\u4E0D\u8FD4\u56DE\u5B8C\u6574\u4EFB\u52A1\u5B9E\u4F53\u3002action \u6E05\u5355\uFF08\u62EC\u53F7\u5185\u4E3A\u8BE5 action \u5FC5\u586B\u53C2\u6570\uFF09\uFF1Acreate(templateId,taskTitle,track\uFF1B\u53EF\u9009 type=feature|bugfix|ui-tweak|research\u3001skipNodes\u3001projectId\uFF1BtemplateId \u652F\u6301 code|id \u53CC\u5F62\u6001\u2014\u2014code \u4E3A\u6A21\u677F\u4E1A\u52A1\u6807\u8BC6\uFF08\u9879\u76EE\u5185\u552F\u4E00\u3001kebab-case \u5FC5\u542B\u8FDE\u5B57\u7B26\uFF0C\u5982 full-workflow\uFF09\uFF0C\u63A8\u8350\u5F15\u7528\u5F62\u6001\uFF0C\u5BFB\u5740\u987B\u914D projectId \u6307\u5B9A\u9879\u76EE\u57DF\uFF1B24-hex \u6570\u636E\u5E93 id \u76F4\u67E5\u517C\u5BB9\uFF1Bcode \u5F62\u6001\u4E0D\u5B58\u5728\u65F6\u9519\u8BEF\u542B candidates \u76F8\u8FD1\u5019\u9009\u6E05\u5355\uFF08id/code/name \u22645 \u6761\uFF09\uFF1B\u54CD\u5E94 {task, firstNode}\u2014\u2014firstNode \u5373\u9996\u8282\u70B9\u5B8C\u6574\u8D44\u6599\u5305\uFF0C\u514D\u8C03 context)\uFF1Bquery(taskId \u8FD4\u56DE\u5355\u4EFB\u52A1\u8BE6\u60C5\uFF0C\u7F3A\u7701\u8FD4\u56DE\u5217\u8868\uFF0C\u53EF\u9009 status/track/projectId/page/limit)\uFF1Bcontext(taskId\uFF1B\u53EF\u9009 view=basic|full\u2014\u2014basic \u7F3A\u7701\u4E0D\u643A\u5E26 artifact \u5168\u6587\u5FEB\u7167\uFF0Cfull \u65AD\u70B9\u7EED\u8DD1\u9700\u5386\u53F2\u4EA7\u7269\u5168\u6587\u65F6\u7528\u3002\u26A0 \u514D\u91CD\u8BFB\uFF1Aadvance/approve \u6D41\u8F6C\u54CD\u5E94\u5DF2\u542B\u4E0B\u4E00\u8282\u70B9\u5B8C\u6574\u8D44\u6599\u5305\uFF0C\u540C\u4F1A\u8BDD\u5185\u6D41\u8F6C\u540E\u76F4\u63A5\u5F00\u5DE5\u3001\u65E0\u9700\u518D\u8C03 context\uFF1B\u4EC5\u65B0\u4F1A\u8BDD/\u65AD\u70B9\u7EED\u8DD1\u8C03\u7528)\uFF1Bnode(taskId,view=prompt|skills\uFF1BnodeId \u7F3A\u7701\u7528\u5F53\u524D\u8282\u70B9\uFF1B\u26A0 view \u503C\u968F action \u4E0D\u540C\uFF1Anode\u2192prompt|skills\uFF0Ccontext\u2192basic|full\uFF0C\u9519\u914D\u62A5\u9519)\uFF1Badvance(taskId\uFF1Bnote \u5199 history\u3001summary \u5199 nodeRecords\uFF0C\u4E24\u4F4D\u72EC\u7ACB\uFF1B\u54CD\u5E94\u5DF2\u542B\u4E0B\u4E00\u8282\u70B9\u8D44\u6599\u5305\uFF0C\u540C\u4F1A\u8BDD\u514D\u91CD\u8BFB context)\uFF1Bapprove(taskId,decision=approved|rejected\uFF1B\u53EF\u9009 comment\uFF1B\u54CD\u5E94\u5DF2\u542B\u4E0B\u4E00\u8282\u70B9\u8D44\u6599\u5305\uFF0C\u540C\u4F1A\u8BDD\u514D\u91CD\u8BFB context)\uFF1Bpause(taskId\uFF1B\u53EF\u9009 reason)\uFF1Bresume(taskId\uFF1B\u53EF\u9009 resumeNote)\uFF1Bcancel(taskId\uFF1B\u53EF\u9009 reason 1-500 \u5B57\u7B26\uFF1B\u26A0 \u7EC8\u6001\u4E0D\u53EF\u9006\u2014\u2014active/paused \u53EF\u53D6\u6D88\uFF0Ccompleted/cancelled \u62D2\u7EDD\u5E76\u8FD4\u56DE TASK_TERMINATED\uFF1B\u53D6\u6D88\u540E\u7ECF\u672C\u5DE5\u5177\u7684\u6D41\u8F6C\u4E0E\u8BB0\u5F55\u5199\u64CD\u4F5C\u88AB\u62D2)\uFF1Bhistory(taskId)\uFF1Binstance(taskId\u2014\u2014\u67E5\u770B\u4EFB\u52A1 DAG \u5B9E\u4F8B\u5FEB\u7167\uFF1A\u521B\u5EFA\u4EFB\u52A1\u65F6\u51BB\u7ED3\u7684\u6A21\u677F\u5B9E\u4F8B\uFF0C\u6A21\u677F\u540E\u7EED\u53D8\u66F4\u4E0D\u56DE\u6EAF)\u3002\u8BB0\u5F55\u5199\u5165\uFF1Arecord-set(taskId,node,summary)\uFF1Brecord-check-add(taskId,node,item\uFF1B\u53EF\u9009 passed \u7F3A\u7701 true\uFF1B\u56DE\u6267 entry.id \u4F9B record-check-patch \u5B9A\u4F4D)\uFF1Brecord-check-patch(taskId,node,checkId\uFF1B\u53EF\u9009 passed)\uFF1Brecord-artifact-add(taskId,node,artifactType=prd|tech|code|test|doc|other\uFF1Bpath \u7EAF\u5F15\u7528 / file \u8BFB\u672C\u673A\u6587\u4EF6 / content \u76F4\u4F20\u5168\u6587\u2014\u2014file \u4E0E content\u3001file \u4E0E path \u4E92\u65A5\uFF0Ccontent \u53EF\u4E0E path \u6210\u5BF9\u6216\u5355\u72EC\uFF0C\u5355\u72EC\u65F6\u767B\u8BB0\u503C\u5408\u6210 mcp-inline/<type>\uFF1B\u53EF\u9009 note)\uFF1Brecord-confirm(taskId,node,quote\u2014\u2014\u6682\u505C\u70B9\u7528\u6237\u786E\u8BA4\u539F\u6587\u9010\u5B57)\uFF1Brecord-decision-add(taskId,node,topic,decisionText)\uFF1Brecord-review-set(taskId,node,verdict=pass|fail,rounds,critical)\u3002\u9700\u6C42\u6587\u6863\uFF1Adoc-set(taskId\uFF1Bwhat/why/trackNote \u81F3\u5C11\u4F20\u4E00)\uFF1Bdoc-acceptance-add(taskId,text)\uFF1Bdoc-non-goal-add(taskId,text)\u3002\u7D20\u6750\uFF1Aarchnote-add(taskId,text)\u3002\u6279\u91CF\u5F62\u6001\uFF08\u63A8\u8350\uFF0C\u516D\u7C7B\u540C\u6784\uFF09\uFF1Arecord-check-add \u4F20 checkItems=[{item,passed?}]\u3001record-artifact-add \u4F20 artifactEntries=[{artifactType,path?/file?/content?,note?}]\u3001record-decision-add \u4F20 decisionEntries=[{topic,decisionText}]\u3001doc-acceptance-add/doc-non-goal-add/archnote-add \u4F20 textItems=[string]\u2014\u2014\u6279\u91CF\u53C2\u6570\u4E0E\u5355\u6761\u53C2\u6570\u4E8C\u9009\u4E00\uFF0C\u4E00\u6B21\u8C03\u7528\u5199\u591A\u6761\uFF08\u4E0A\u9650 50 \u6761/\u6279\uFF0Cartifact \u5168\u6587\u5FEB\u7167\u603B\u91CF \u22642M \u5B57\u7B26/\u6279\uFF09\uFF1B\u90E8\u5206\u5931\u8D25\u4FDD\u7559\u6210\u529F\u6761\u76EE\u5E76\u9010\u6761\u62A5\u544A\uFF08failures[].index=\u539F\u59CB\u63D0\u4EA4\u5E8F\uFF0C\u53EA\u91CD\u8BD5\u5931\u8D25\u9879\uFF09\uFF0Capplied=0 \u6574\u4F53\u62A5\u5931\u8D25\u3002",
|
|
1691
|
+
"task \u8D44\u6E90\u57DF\u805A\u5408\u5DE5\u5177\uFF08\u4EFB\u52A1\u5168\u64CD\u4F5C\u7ECF\u672C\u5DE5\u5177 + action \u53C2\u6570\uFF09\u3002action \u5FC5\u586B\uFF1B\u8C03\u7528\u65B9\u5E94\u5728 fieldMask \u4E2D\u5217\u51FA\u672C\u6B21\u771F\u5B9E\u63D0\u4F9B\u7684\u53EF\u9009\u5B57\u6BB5\uFF0Cmask \u5916\u7531\u5BBF\u4E3B\u81EA\u52A8\u586B\u5145\u7684\u7A7A\u4E32\u3001\u7A7A\u6570\u7EC4\u3001false\u30010 \u5747\u5FFD\u7565\uFF0Cmask \u5185\u7A7A\u6570\u7EC4/false \u8868\u793A\u663E\u5F0F\u6E05\u7A7A\u6216\u5173\u95ED\uFF1B\u5404 action \u56FA\u5B9A\u5FC5\u586B\u5B57\u6BB5\u65E0\u9700\u5199\u5165 mask\u3002\u5176\u4F59\u53C2\u6570\u5168\u53EF\u9009\u3001\u6309 action \u8FD0\u884C\u65F6\u6821\u9A8C\u5FC5\u586B\uFF08\u7F3A\u5931\u8FD4\u56DE\u5931\u8D25\u4E09\u8981\u7D20\uFF1A\u5BF9\u8C61+\u6839\u56E0+\u4FEE\u590D\u6307\u5F15\uFF09\u3002projectId \u4E3A key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\u4E3A 24-hex id\uFF1B\u663E\u5F0F\u6307\u5B9A\u89E3\u6790\u5931\u8D25\u62A5\u9519\u4E0D\u515C\u5E95\uFF1B\u7F3A\u7701\u8BED\u4E49\u6309 action\uFF1Acreate \u843D\u9ED8\u8BA4\u9879\u76EE\u94FE\uFF08\u5DE5\u4F5C\u533A defaultProject \u5931\u6548\u62A5\u9519\uFF0C\u65E0\u914D\u7F6E\u4E0D\u4F20\u7531 server \u6309\u6A21\u677F\u5F52\u5C5E\u515C\u5E95\uFF09\uFF0Cquery \u4E0D\u8FC7\u6EE4\uFF08\u5168\u5C40\u67E5\u8BE2\uFF09\u3002\u5199\u64CD\u4F5C\uFF08create/doc-*/record-*/archnote-add/pause/resume/cancel\uFF09\u54CD\u5E94\u4E3A\u8F7B\u91CF\u56DE\u6267\uFF1A{taskId, updated(\u89E6\u53CA\u5B57\u6BB5\u8DEF\u5F84), entry(\u65B0\u6761\u76EE id+kind\uFF0C\u4F9B\u540E\u7EED patch \u5B9A\u4F4D), echo(\u5199\u5165\u5185\u5BB9\u56DE\u663E), updatedAt, task(\u4EFB\u52A1\u8FDB\u5EA6\u6458\u8981 progress: {completed,total})}\u2014\u2014\u4E0D\u8FD4\u56DE\u5B8C\u6574\u4EFB\u52A1\u5B9E\u4F53\u3002action \u6E05\u5355\uFF08\u62EC\u53F7\u5185\u4E3A\u8BE5 action \u5FC5\u586B\u53C2\u6570\uFF09\uFF1Acreate(templateId,taskTitle,track\uFF1B\u53EF\u9009 type=feature|bugfix|ui-tweak|research\u3001skipNodes\u3001projectId\uFF1BtemplateId \u652F\u6301 code|id \u53CC\u5F62\u6001\u2014\u2014code \u4E3A\u6A21\u677F\u4E1A\u52A1\u6807\u8BC6\uFF08\u9879\u76EE\u5185\u552F\u4E00\u3001kebab-case \u5FC5\u542B\u8FDE\u5B57\u7B26\uFF0C\u5982 full-workflow\uFF09\uFF0C\u63A8\u8350\u5F15\u7528\u5F62\u6001\uFF0C\u5BFB\u5740\u987B\u914D projectId \u6307\u5B9A\u9879\u76EE\u57DF\uFF1B24-hex \u6570\u636E\u5E93 id \u76F4\u67E5\u517C\u5BB9\uFF1Bcode \u5F62\u6001\u4E0D\u5B58\u5728\u65F6\u9519\u8BEF\u542B candidates \u76F8\u8FD1\u5019\u9009\u6E05\u5355\uFF08id/code/name \u22645 \u6761\uFF09\uFF1B\u54CD\u5E94 {task, firstNode}\u2014\u2014firstNode \u5373\u9996\u8282\u70B9\u5B8C\u6574\u8D44\u6599\u5305\uFF0C\u514D\u8C03 context)\uFF1Bquery(taskId \u8FD4\u56DE\u5355\u4EFB\u52A1\u8BE6\u60C5\uFF0C\u7F3A\u7701\u8FD4\u56DE\u5217\u8868\uFF0C\u53EF\u9009 status/track/projectId/page/limit)\uFF1Bcontext(taskId\uFF1B\u53EF\u9009 view=basic|full\u2014\u2014basic \u7F3A\u7701\u4E0D\u643A\u5E26 artifact \u5168\u6587\u5FEB\u7167\uFF0Cfull \u65AD\u70B9\u7EED\u8DD1\u9700\u5386\u53F2\u4EA7\u7269\u5168\u6587\u65F6\u7528\u3002\u26A0 \u514D\u91CD\u8BFB\uFF1Aadvance/approve \u6D41\u8F6C\u54CD\u5E94\u5DF2\u542B\u4E0B\u4E00\u8282\u70B9\u5B8C\u6574\u8D44\u6599\u5305\uFF0C\u540C\u4F1A\u8BDD\u5185\u6D41\u8F6C\u540E\u76F4\u63A5\u5F00\u5DE5\u3001\u65E0\u9700\u518D\u8C03 context\uFF1B\u4EC5\u65B0\u4F1A\u8BDD/\u65AD\u70B9\u7EED\u8DD1\u8C03\u7528)\uFF1Bnode(taskId,view=prompt|skills\uFF1BnodeId \u7F3A\u7701\u7528\u5F53\u524D\u8282\u70B9\uFF1B\u26A0 view \u503C\u968F action \u4E0D\u540C\uFF1Anode\u2192prompt|skills\uFF0Ccontext\u2192basic|full\uFF0C\u9519\u914D\u62A5\u9519)\uFF1Badvance(taskId\uFF1Bnote \u5199 history\u3001summary \u5199 nodeRecords\uFF0C\u4E24\u4F4D\u72EC\u7ACB\uFF1B\u54CD\u5E94\u5DF2\u542B\u4E0B\u4E00\u8282\u70B9\u8D44\u6599\u5305\uFF0C\u540C\u4F1A\u8BDD\u514D\u91CD\u8BFB context)\uFF1Bapprove(taskId,decision=approved|rejected\uFF1B\u53EF\u9009 comment\uFF1B\u54CD\u5E94\u5DF2\u542B\u4E0B\u4E00\u8282\u70B9\u8D44\u6599\u5305\uFF0C\u540C\u4F1A\u8BDD\u514D\u91CD\u8BFB context)\uFF1Bpause(taskId\uFF1B\u53EF\u9009 reason)\uFF1Bresume(taskId\uFF1B\u53EF\u9009 resumeNote)\uFF1Bcancel(taskId\uFF1B\u53EF\u9009 reason 1-500 \u5B57\u7B26\uFF1B\u26A0 \u7EC8\u6001\u4E0D\u53EF\u9006\u2014\u2014active/paused \u53EF\u53D6\u6D88\uFF0Ccompleted/cancelled \u62D2\u7EDD\u5E76\u8FD4\u56DE TASK_TERMINATED\uFF1B\u53D6\u6D88\u540E\u7ECF\u672C\u5DE5\u5177\u7684\u6D41\u8F6C\u4E0E\u8BB0\u5F55\u5199\u64CD\u4F5C\u88AB\u62D2)\uFF1Bhistory(taskId)\uFF1Binstance(taskId\u2014\u2014\u67E5\u770B\u4EFB\u52A1 DAG \u5B9E\u4F8B\u5FEB\u7167\uFF1A\u521B\u5EFA\u4EFB\u52A1\u65F6\u51BB\u7ED3\u7684\u6A21\u677F\u5B9E\u4F8B\uFF0C\u6A21\u677F\u540E\u7EED\u53D8\u66F4\u4E0D\u56DE\u6EAF)\u3002\u8BB0\u5F55\u5199\u5165\uFF1Arecord-set(taskId,node,summary)\uFF1Brecord-check-add(taskId,node,item\uFF1B\u53EF\u9009 passed \u7F3A\u7701 true\uFF1B\u56DE\u6267 entry.id \u4F9B record-check-patch \u5B9A\u4F4D)\uFF1Brecord-check-patch(taskId,node,checkId\uFF1B\u53EF\u9009 passed)\uFF1Brecord-artifact-add(taskId,node,artifactType=prd|tech|code|test|doc|other\uFF1Bpath \u7EAF\u5F15\u7528 / file \u8BFB\u672C\u673A\u6587\u4EF6 / content \u76F4\u4F20\u5168\u6587\u2014\u2014file \u4E0E content\u3001file \u4E0E path \u4E92\u65A5\uFF0Ccontent \u53EF\u4E0E path \u6210\u5BF9\u6216\u5355\u72EC\uFF0C\u5355\u72EC\u65F6\u767B\u8BB0\u503C\u5408\u6210 mcp-inline/<type>\uFF1B\u53EF\u9009 note)\uFF1Brecord-confirm(taskId,node,quote\u2014\u2014\u6682\u505C\u70B9\u7528\u6237\u786E\u8BA4\u539F\u6587\u9010\u5B57)\uFF1Brecord-decision-add(taskId,node,topic,decisionText)\uFF1Brecord-review-set(taskId,node,verdict=pass|fail,rounds,critical)\u3002\u9700\u6C42\u6587\u6863\uFF1Adoc-set(taskId\uFF1Bwhat/why/trackNote \u81F3\u5C11\u4F20\u4E00)\uFF1Bdoc-acceptance-add(taskId,text)\uFF1Bdoc-non-goal-add(taskId,text)\u3002\u7D20\u6750\uFF1Aarchnote-add(taskId,text)\u3002\u6279\u91CF\u5F62\u6001\uFF08\u63A8\u8350\uFF0C\u516D\u7C7B\u540C\u6784\uFF09\uFF1Arecord-check-add \u4F20 checkItems=[{item,passed?}]\u3001record-artifact-add \u4F20 artifactEntries=[{artifactType,path?/file?/content?,note?}]\u3001record-decision-add \u4F20 decisionEntries=[{topic,decisionText}]\u3001doc-acceptance-add/doc-non-goal-add/archnote-add \u4F20 textItems=[string]\u2014\u2014\u6279\u91CF\u53C2\u6570\u4E0E\u5355\u6761\u53C2\u6570\u4E8C\u9009\u4E00\uFF0C\u4E00\u6B21\u8C03\u7528\u5199\u591A\u6761\uFF08\u4E0A\u9650 50 \u6761/\u6279\uFF0Cartifact \u5168\u6587\u5FEB\u7167\u603B\u91CF \u22642M \u5B57\u7B26/\u6279\uFF09\uFF1B\u90E8\u5206\u5931\u8D25\u4FDD\u7559\u6210\u529F\u6761\u76EE\u5E76\u9010\u6761\u62A5\u544A\uFF08failures[].index=\u539F\u59CB\u63D0\u4EA4\u5E8F\uFF0C\u53EA\u91CD\u8BD5\u5931\u8D25\u9879\uFF09\uFF0Capplied=0 \u6574\u4F53\u62A5\u5931\u8D25\u3002",
|
|
1612
1692
|
taskArgs,
|
|
1613
1693
|
async (rawArgs) => {
|
|
1614
1694
|
const masked = applyFieldMask(rawArgs, TASK_FIELD_SPECS);
|
|
@@ -1620,13 +1700,15 @@ function createMcpServer() {
|
|
|
1620
1700
|
if (templateId === void 0 || taskTitle === void 0 || track === void 0) {
|
|
1621
1701
|
return requireError("create", ["templateId", "taskTitle", "track"], args);
|
|
1622
1702
|
}
|
|
1703
|
+
const projectR = await resolveScopedProject(client, args.projectId, "ws-default", { channel: "mcp" });
|
|
1704
|
+
if (!projectR.success) return mcpContent(projectR);
|
|
1623
1705
|
const input = {
|
|
1624
1706
|
title: taskTitle,
|
|
1625
1707
|
track,
|
|
1626
1708
|
dagTemplateId: templateId,
|
|
1627
1709
|
...args.type !== void 0 ? { type: args.type } : {},
|
|
1628
1710
|
...args.skipNodes !== void 0 ? { skipNodes: args.skipNodes } : {},
|
|
1629
|
-
...
|
|
1711
|
+
...projectR.data.projectId !== void 0 ? { projectId: projectR.data.projectId } : {}
|
|
1630
1712
|
};
|
|
1631
1713
|
return mcpContent(await handleCreateTask(client, input));
|
|
1632
1714
|
}
|
|
@@ -1640,11 +1722,17 @@ function createMcpServer() {
|
|
|
1640
1722
|
if (args.taskId) {
|
|
1641
1723
|
return mcpContent(await handleQueryState(client, args.taskId));
|
|
1642
1724
|
}
|
|
1725
|
+
let queryProjectId;
|
|
1726
|
+
if (args.projectId !== void 0 && args.projectId.trim().length > 0) {
|
|
1727
|
+
const pr = await resolveScopedProject(client, args.projectId, "explicit-only", { channel: "mcp" });
|
|
1728
|
+
if (!pr.success) return mcpContent(pr);
|
|
1729
|
+
queryProjectId = pr.data.projectId;
|
|
1730
|
+
}
|
|
1643
1731
|
return mcpContent(
|
|
1644
1732
|
await handleListTasks(client, {
|
|
1645
1733
|
...args.status !== void 0 ? { status: args.status } : {},
|
|
1646
1734
|
...args.track !== void 0 ? { track: args.track } : {},
|
|
1647
|
-
...
|
|
1735
|
+
...queryProjectId !== void 0 ? { projectId: queryProjectId } : {},
|
|
1648
1736
|
...args.page !== void 0 ? { page: args.page } : {},
|
|
1649
1737
|
...args.limit !== void 0 ? { limit: args.limit } : {}
|
|
1650
1738
|
})
|
|
@@ -1942,26 +2030,38 @@ function createMcpServer() {
|
|
|
1942
2030
|
);
|
|
1943
2031
|
server.tool(
|
|
1944
2032
|
"siming_template",
|
|
1945
|
-
"DAG \u6A21\u677F\u53EA\u8BFB\u67E5\u8BE2\uFF08\u4EFB\u52A1\u521B\u5EFA\u524D\u9009\u6A21\u677F/\u6838\u5BF9\u6A21\u677F\u7ED3\u6784\u7528\uFF1B\u672C\u5DE5\u5177\u65E0\u5199\u64CD\u4F5C\uFF09\u3002action\uFF1Alist=\u6A21\u677F\u5217\u8868\uFF08\u6982\u8981\u6295\u5F71\uFF0C\u542B id/code/name/version/isDefault/projectId/nodeCount/nodes \u6982\u8981/pausePoints/description\uFF0C\u4E0D\u542B\u8282\u70B9 prompt \u5168\u6587\uFF1B\u53EF\u9009 projectId \u8FC7\u6EE4\u9879\u76EE\u57DF\uFF1B\u8FD4\u56DE code \u4E3A\u540E\u7EED\u5F15\u7528\u6A21\u677F\u7684\u63A8\u8350\u5F62\u6001\uFF09\uFF1Bshow=\u6A21\u677F\u8BE6\u60C5\uFF08\u542B\u5168\u90E8\u8282\u70B9 prompt\uFF1BtemplateId \u652F\u6301 code|id \u53CC\u5F62\u6001\u2014\u2014code \u4E3A\u4E1A\u52A1\u6807\u8BC6\uFF08\u9879\u76EE\u5185\u552F\u4E00\u3001\u521B\u5EFA\u540E\u4E0D\u53EF\u53D8\u3001kebab-case \u5FC5\u542B\u8FDE\u5B57\u7B26\u4E14\u975E\u7EAF 24-hex \u5F62\u6001\uFF0C\u5982 full-workflow\uFF09\uFF0Ccode \u5F62\u6001\u5BFB\u5740\u987B\u914D projectId \u6307\u5B9A\u9879\u76EE\u57DF\uFF1B24 \u4F4D\u6570\u636E\u5E93 id \u76F4\u67E5\u517C\u5BB9\uFF0C\u65E0\u9700 projectId\uFF09\u3002\u6A21\u677F\u4E0D\u5B58\u5728\u65F6\u9519\u8BEF\u4FE1\u606F\u542B candidates \u5019\u9009\u6E05\u5355\uFF08\u9879\u76EE\u5185\u76F8\u8FD1\u6A21\u677F\u7684 id/code/name\uFF0C\u6309\u76F8\u5173\u5EA6\u6392\u5E8F\u4E0A\u9650 5 \u6761\uFF09\u2014\u2014\u8F6C\u5F55\u9519\u8BEF\u53EF\u636E\u6E05\u5355\u5F53\u573A\u7EA0\u6B63\u3002\u505C\u7528\u6A21\u677F\uFF08Web \u7BA1\u7406\u53F0\u542F\u505C\uFF09\uFF1Alist \u9ED8\u8BA4\u4E0D\u542B\u505C\u7528\u6A21\u677F\uFF1Bshow \u6309 code|id \u4ECD\u53EF\u8BFB\uFF1B\u7528\u505C\u7528\u6A21\u677F\u521B\u5EFA\u4EFB\u52A1\u88AB\u62D2\uFF08409 TEMPLATE_DISABLED\uFF09\u2014\u2014\u9700\u5728 Web \u7BA1\u7406\u53F0\u91CD\u65B0\u542F\u7528\u540E\u518D\u5EFA\u4EFB\u52A1\u3002\u6A21\u677F\u5199\u5165\u4E0E\u6F14\u8FDB\u4E0D\u5728 MCP\uFF1A\u5BFC\u5165\uFF08\u542B\u540C\u540D\u66F4\u65B0/\u9884\u89C8/\u5B8C\u6574\u4F9D\u8D56\u95ED\u5305 bundle\uFF09\u7528 CLI `siming dag template import`\uFF0C\u6A21\u677F\u5347\u7EA7\u9884\u68C0/\u6267\u884C\u7528 CLI `siming dag template upgrade plan/apply`\uFF08bash \u6267\u884C\uFF0C--help \u67E5\u7528\u6CD5\uFF09\u3002",
|
|
2033
|
+
"DAG \u6A21\u677F\u53EA\u8BFB\u67E5\u8BE2\uFF08\u4EFB\u52A1\u521B\u5EFA\u524D\u9009\u6A21\u677F/\u6838\u5BF9\u6A21\u677F\u7ED3\u6784\u7528\uFF1B\u672C\u5DE5\u5177\u65E0\u5199\u64CD\u4F5C\uFF09\u3002action\uFF1Alist=\u6A21\u677F\u5217\u8868\uFF08\u6982\u8981\u6295\u5F71\uFF0C\u542B id/code/name/version/isDefault/projectId/nodeCount/nodes \u6982\u8981/pausePoints/description\uFF0C\u4E0D\u542B\u8282\u70B9 prompt \u5168\u6587\uFF1B\u53EF\u9009 projectId \u8FC7\u6EE4\u9879\u76EE\u57DF\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\uFF0C\u7A7A/\u672A\u4F20\u4E0D\u8FC7\u6EE4\uFF1B\u8FD4\u56DE code \u4E3A\u540E\u7EED\u5F15\u7528\u6A21\u677F\u7684\u63A8\u8350\u5F62\u6001\uFF09\uFF1Bshow=\u6A21\u677F\u8BE6\u60C5\uFF08\u542B\u5168\u90E8\u8282\u70B9 prompt\uFF1BtemplateId \u652F\u6301 code|id \u53CC\u5F62\u6001\u2014\u2014code \u4E3A\u4E1A\u52A1\u6807\u8BC6\uFF08\u9879\u76EE\u5185\u552F\u4E00\u3001\u521B\u5EFA\u540E\u4E0D\u53EF\u53D8\u3001kebab-case \u5FC5\u542B\u8FDE\u5B57\u7B26\u4E14\u975E\u7EAF 24-hex \u5F62\u6001\uFF0C\u5982 full-workflow\uFF09\uFF0Ccode \u5F62\u6001\u5BFB\u5740\u987B\u914D projectId \u6307\u5B9A\u9879\u76EE\u57DF\u2014\u2014key|id \u53CC\u5F62\u6001\u81EA\u52A8\u5F52\u4E00\uFF0C\u7F3A\u7701\u6309\u5DE5\u4F5C\u533A defaultProject\uFF08\u5931\u6548\u62A5\u9519\uFF09\uFF0C\u65E0\u914D\u7F6E\u4E0D\u4F20\u7531 server \u63D0\u793A\u8865\u57DF\uFF1B24 \u4F4D\u6570\u636E\u5E93 id \u76F4\u67E5\u517C\u5BB9\uFF0C\u65E0\u9700 projectId\uFF09\u3002\u6A21\u677F\u4E0D\u5B58\u5728\u65F6\u9519\u8BEF\u4FE1\u606F\u542B candidates \u5019\u9009\u6E05\u5355\uFF08\u9879\u76EE\u5185\u76F8\u8FD1\u6A21\u677F\u7684 id/code/name\uFF0C\u6309\u76F8\u5173\u5EA6\u6392\u5E8F\u4E0A\u9650 5 \u6761\uFF09\u2014\u2014\u8F6C\u5F55\u9519\u8BEF\u53EF\u636E\u6E05\u5355\u5F53\u573A\u7EA0\u6B63\u3002\u505C\u7528\u6A21\u677F\uFF08Web \u7BA1\u7406\u53F0\u542F\u505C\uFF09\uFF1Alist \u9ED8\u8BA4\u4E0D\u542B\u505C\u7528\u6A21\u677F\uFF1Bshow \u6309 code|id \u4ECD\u53EF\u8BFB\uFF1B\u7528\u505C\u7528\u6A21\u677F\u521B\u5EFA\u4EFB\u52A1\u88AB\u62D2\uFF08409 TEMPLATE_DISABLED\uFF09\u2014\u2014\u9700\u5728 Web \u7BA1\u7406\u53F0\u91CD\u65B0\u542F\u7528\u540E\u518D\u5EFA\u4EFB\u52A1\u3002\u6A21\u677F\u5199\u5165\u4E0E\u6F14\u8FDB\u4E0D\u5728 MCP\uFF1A\u5BFC\u5165\uFF08\u542B\u540C\u540D\u66F4\u65B0/\u9884\u89C8/\u5B8C\u6574\u4F9D\u8D56\u95ED\u5305 bundle\uFF09\u7528 CLI `siming dag template import`\uFF0C\u6A21\u677F\u5347\u7EA7\u9884\u68C0/\u6267\u884C\u7528 CLI `siming dag template upgrade plan/apply`\uFF08bash \u6267\u884C\uFF0C--help \u67E5\u7528\u6CD5\uFF09\u3002",
|
|
1946
2034
|
templateArgs,
|
|
1947
2035
|
async (args) => {
|
|
1948
2036
|
switch (args.action) {
|
|
1949
2037
|
case "list": {
|
|
1950
|
-
|
|
2038
|
+
let listProjectId;
|
|
2039
|
+
if (args.projectId !== void 0 && args.projectId.trim().length > 0) {
|
|
2040
|
+
const pr = await resolveScopedProject(client, args.projectId, "explicit-only", { channel: "mcp" });
|
|
2041
|
+
if (!pr.success) return mcpContent(pr);
|
|
2042
|
+
listProjectId = pr.data.projectId;
|
|
2043
|
+
}
|
|
2044
|
+
const result = await handleListTemplates(client, listProjectId);
|
|
1951
2045
|
if (!result.success) return mcpContent(result);
|
|
1952
2046
|
return mcpContent(ok2(result.data.map(toTemplateSummary)));
|
|
1953
2047
|
}
|
|
1954
2048
|
case "show": {
|
|
1955
|
-
const { templateId
|
|
2049
|
+
const { templateId } = args;
|
|
1956
2050
|
if (templateId === void 0) return requireError("show", ["templateId"], args);
|
|
1957
|
-
|
|
2051
|
+
let showProjectId;
|
|
2052
|
+
if (!/^[a-f0-9]{24}$/.test(templateId)) {
|
|
2053
|
+
const pr = await resolveScopedProject(client, args.projectId, "ws-default", { channel: "mcp" });
|
|
2054
|
+
if (!pr.success) return mcpContent(pr);
|
|
2055
|
+
showProjectId = pr.data.projectId;
|
|
2056
|
+
}
|
|
2057
|
+
return mcpContent(await handleGetTemplate(client, templateId, showProjectId));
|
|
1958
2058
|
}
|
|
1959
2059
|
}
|
|
1960
2060
|
}
|
|
1961
2061
|
);
|
|
1962
2062
|
server.tool(
|
|
1963
2063
|
"siming_issue",
|
|
1964
|
-
`\u95EE\u9898\u6C60\u5DE5\u5177\uFF08T202609150002\uFF09\uFF1A\u5C0F\u95EE\u9898\u4F4E\u6210\u672C\u5165\u6C60\uFF0C\u6C89\u6DC0\u540E\u7EDF\u4E00\u6574\u7406\u8F6C\u4EFB\u52A1\uFF08\u8F6C\u4EFB\u52A1/\u6574\u7406\u91CD\u4EA4\u4E92\u8D70 CLI siming issue convert \u6216 Web\uFF0C\u4E0D\u5728\u672C\u5DE5\u5177\u9762\uFF09\u3002action\uFF1Acreate(title \u5FC5\u586B 1-200 \u5B57\uFF1B\u53EF\u9009 description\u3001projectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\u4E3A 24-hex id\uFF08hex \u96F6\u7F51\u7EDC\u5F00\u9500\u76F4\u901A\uFF09\uFF1B\u663E\u5F0F\u6307\u5B9A\u89E3\u6790\u5931\u8D25\u62A5\u9519\u4E0D\u515C\u5E95\uFF1B\u7F3A\u7701\u94FE\uFF1A\u672A\u4F20\u6216\u7A7A\u4E32\u65F6\u6309\u5DE5\u4F5C\u533A defaultProject \u89E3\u6790\uFF0C\u65E0\u914D\u7F6E\
|
|
2064
|
+
`\u95EE\u9898\u6C60\u5DE5\u5177\uFF08T202609150002\uFF1BT202609200001 \u5F55\u5165\u5BA1\u6279\u95E8\u69DB\uFF09\uFF1A\u5C0F\u95EE\u9898\u4F4E\u6210\u672C\u5165\u6C60\uFF0C\u6C89\u6DC0\u540E\u7EDF\u4E00\u6574\u7406\u8F6C\u4EFB\u52A1\uFF08\u8F6C\u4EFB\u52A1/\u76F4\u63A5\u6807\u8BB0\u5B8C\u6210\u7B49\u6574\u7406\u91CD\u4EA4\u4E92\u8D70 CLI siming issue convert / siming issue done \u6216 Web\uFF0C\u4E0D\u5728\u672C\u5DE5\u5177\u9762\uFF09\u3002action\uFF1Acreate(title \u5FC5\u586B 1-200 \u5B57\uFF1Bapproved \u5FC5\u586B 1-500 \u5B57\u2014\u2014\u4EBA\u7C7B\u5BA1\u6279\u539F\u8BDD\u9010\u5B57\u5F15\u7528\uFF1A\u5F55\u5165\u524D\u5FC5\u987B\u5148\u5411\u7528\u6237\u5B8C\u6574\u5448\u73B0\u95EE\u9898\uFF08\u73B0\u8C61/\u6839\u56E0/\u5F71\u54CD/\u5EFA\u8BAE\uFF09\u5E76\u83B7\u7528\u6237\u660E\u786E\u6279\u51C6\uFF0C\u503C = \u7528\u6237\u6279\u51C6\u65F6\u8F93\u5165\u7684\u539F\u8BDD\uFF08\u5982\u300COK\uFF0C\u8BB0\u5F55\u300D\uFF09\uFF0C\u7981\u6B62\u4EE3\u586B\u3001\u7F16\u9020\u6216\u4EE5\u8BC4\u4F30\u6027\u8BED\u8A00\u4EE3\u66FF\uFF1B\u4F2A\u9020\u5C5E\u8FDD\u89C4\u5E76\u7559\u5BA1\u8BA1\u75D5\u8FF9\uFF1B\u539F\u8BDD\u843D\u5E93\u4F9B\u4E8B\u540E\u5BA1\u8BA1\uFF08query \u4E0E Web \u8BE6\u60C5\u9875\u53EF\u67E5\uFF09\uFF1B\u53EF\u9009 description\u3001projectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\u4E3A 24-hex id\uFF08hex \u96F6\u7F51\u7EDC\u5F00\u9500\u76F4\u901A\uFF09\uFF1B\u663E\u5F0F\u6307\u5B9A\u89E3\u6790\u5931\u8D25\u62A5\u9519\u4E0D\u515C\u5E95\uFF1B\u7F3A\u7701\u94FE\uFF1A\u672A\u4F20\u6216\u7A7A\u4E32\u65F6\u6309\u5DE5\u4F5C\u533A defaultProject \u89E3\u6790\uFF08\u5931\u6548\u62A5\u9519\uFF09\uFF0C\u65E0\u914D\u7F6E\u65F6\u4E0D\u4F20 projectId \u7531 server \u6309 key=default \u515C\u5E95\uFF1B\u5F55\u5165\u540E source=mcp\uFF0C\u7F3A approved \u670D\u52A1\u7AEF 400 \u5E76\u8FD4\u56DE\u81EA\u89E3\u91CA\u6587\u6848)\uFF1Bquery(\u53EF\u9009 view=open|all\u2014\u2014\u7F3A\u7701 open=\u6709\u6548\u672A\u8DDF\u8FDB\u5B8C\uFF0Call=\u5168\u91CF\uFF1Bstatus \u8FC7\u6EE4\u2014\u2014pending|partial|converted|cancelled|done\uFF0C\u663E\u5F0F\u6307\u5B9A\u65F6\u4F18\u5148\u4E8E view\uFF0C\u53EF\u67E5\u5DF2\u53D6\u6D88/\u5DF2\u5B8C\u6210\uFF1BtaskId=\u4EFB\u52A1\u53CD\u67E5\uFF1BprojectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\uFF0C\u7A7A/\u672A\u4F20\u4E0D\u8FC7\u6EE4\uFF08\u663E\u5F0F\u89E3\u6790\u5931\u8D25\u62A5\u9519\uFF09\uFF1Bpage\u22651/limit 1-500\uFF1B\u54CD\u5E94 items \u542B progress {done,cancelled,total})\u3002\u8C03\u7528\u65B9\u5E94\u5728 fieldMask \u4E2D\u5217\u51FA\u672C\u6B21\u771F\u5B9E\u63D0\u4F9B\u7684\u53EF\u9009\u5B57\u6BB5\uFF0Cmask \u5916\u7531\u5BBF\u4E3B\u81EA\u52A8\u586B\u5145\u7684\u7A7A\u4E32\u3001\u7A7A\u6570\u7EC4\u3001false\u30010 \u5747\u5FFD\u7565\uFF1B\u5404 action \u56FA\u5B9A\u5FC5\u586B\u5B57\u6BB5\u65E0\u9700\u5199\u5165 mask\u3002`,
|
|
1965
2065
|
issueArgs,
|
|
1966
2066
|
async (rawArgs) => {
|
|
1967
2067
|
const masked = applyFieldMask(rawArgs, ISSUE_FIELD_SPECS);
|
|
@@ -1969,36 +2069,19 @@ function createMcpServer() {
|
|
|
1969
2069
|
const args = masked.args;
|
|
1970
2070
|
switch (args.action) {
|
|
1971
2071
|
case "create": {
|
|
1972
|
-
const { title } = args;
|
|
1973
|
-
if (title === void 0) {
|
|
1974
|
-
return requireError("create", ["title"], args);
|
|
1975
|
-
}
|
|
1976
|
-
let projectId;
|
|
1977
|
-
const explicitProject = args.projectId !== void 0 && args.projectId.trim().length > 0 ? args.projectId : void 0;
|
|
1978
|
-
if (explicitProject !== void 0) {
|
|
1979
|
-
const resolved = await resolveProjectId(client, explicitProject);
|
|
1980
|
-
if (!resolved.success) {
|
|
1981
|
-
return mcpContent({
|
|
1982
|
-
...resolved,
|
|
1983
|
-
error: {
|
|
1984
|
-
...resolved.error,
|
|
1985
|
-
hint: "MCP \u8C03\u7528\u8BF7\u4F20 projectId \u5B57\u6BB5\uFF08\u9879\u76EE key \u6216 24-hex id \u53CC\u5F62\u6001\uFF0C\u81EA\u52A8\u5F52\u4E00\uFF09\uFF1B\u53EF\u7528 `siming project list` \u67E5\u8BE2\u53EF\u7528\u9879\u76EE"
|
|
1986
|
-
}
|
|
1987
|
-
});
|
|
1988
|
-
}
|
|
1989
|
-
projectId = resolved.data;
|
|
1990
|
-
} else {
|
|
1991
|
-
const wsDefaultProject = readWorkspaceConfig()?.defaultProject;
|
|
1992
|
-
if (wsDefaultProject) {
|
|
1993
|
-
const resolved = await resolveProjectId(client, wsDefaultProject);
|
|
1994
|
-
if (resolved.success) projectId = resolved.data;
|
|
1995
|
-
}
|
|
2072
|
+
const { title, approved } = args;
|
|
2073
|
+
if (title === void 0 || approved === void 0) {
|
|
2074
|
+
return requireError("create", ["title", "approved"], args);
|
|
1996
2075
|
}
|
|
2076
|
+
const projectR = await resolveScopedProject(client, args.projectId, "ws-default", { channel: "mcp" });
|
|
2077
|
+
if (!projectR.success) return mcpContent(projectR);
|
|
2078
|
+
const projectId = projectR.data.projectId;
|
|
1997
2079
|
return mcpContent(
|
|
1998
2080
|
await handleCreateIssue(client, {
|
|
1999
2081
|
title,
|
|
2000
2082
|
...args.description !== void 0 ? { description: args.description } : {},
|
|
2001
|
-
...projectId !== void 0 ? { projectId } : {}
|
|
2083
|
+
...projectId !== void 0 ? { projectId } : {},
|
|
2084
|
+
approved
|
|
2002
2085
|
})
|
|
2003
2086
|
);
|
|
2004
2087
|
}
|
|
@@ -2009,12 +2092,18 @@ function createMcpServer() {
|
|
|
2009
2092
|
if (args.limit !== void 0 && (args.limit < 1 || args.limit > 500)) {
|
|
2010
2093
|
return localError("action=query \u7684 limit \u5FC5\u987B\u4E3A 1-500 \u7684\u6574\u6570");
|
|
2011
2094
|
}
|
|
2095
|
+
let issueQueryProjectId;
|
|
2096
|
+
if (args.projectId !== void 0 && args.projectId.trim().length > 0) {
|
|
2097
|
+
const pr = await resolveScopedProject(client, args.projectId, "explicit-only", { channel: "mcp" });
|
|
2098
|
+
if (!pr.success) return mcpContent(pr);
|
|
2099
|
+
issueQueryProjectId = pr.data.projectId;
|
|
2100
|
+
}
|
|
2012
2101
|
return mcpContent(
|
|
2013
2102
|
await handleListIssues(client, {
|
|
2014
2103
|
view: args.view ?? "open",
|
|
2015
2104
|
...args.status !== void 0 ? { status: args.status } : {},
|
|
2016
2105
|
...args.taskId !== void 0 ? { taskId: args.taskId } : {},
|
|
2017
|
-
...
|
|
2106
|
+
...issueQueryProjectId !== void 0 ? { projectId: issueQueryProjectId } : {},
|
|
2018
2107
|
...args.page !== void 0 ? { page: args.page } : {},
|
|
2019
2108
|
...args.limit !== void 0 ? { limit: args.limit } : {}
|
|
2020
2109
|
})
|
|
@@ -2236,18 +2325,19 @@ var PAGE_DEFAULT = 20;
|
|
|
2236
2325
|
var PAGE_MAX = 500;
|
|
2237
2326
|
function createTaskCommand() {
|
|
2238
2327
|
const task = new Command2("task").description("Task management \u2014 create, advance, approve, pause, resume, cancel, reopen, query");
|
|
2239
|
-
withCommonOpts(task.command("list"), "table").option("--status <s>", "filter by status").option("--track <t>", "filter by track").option("--project <key
|
|
2328
|
+
withCommonOpts(task.command("list"), "table").option("--status <s>", "filter by status").option("--track <t>", "filter by track").option("--project <key|id>", "filter by projectId (key|id)").option("--page <n>", "page number (default 1)", "1").option("--limit <n>", `page size (default ${PAGE_DEFAULT}, max ${PAGE_MAX})`).option("--all", `show all (limit ${PAGE_MAX})`).option("--sort <s>", "sort: progress|createdAt|updatedAt (default progress)").description("List tasks (summary projection: no dagInstance/history payloads)").action(async (opts) => {
|
|
2240
2329
|
const client = createClient(opts.url);
|
|
2241
2330
|
const filters = {};
|
|
2242
2331
|
if (opts.status) filters.status = opts.status;
|
|
2243
2332
|
if (opts.track) filters.track = opts.track;
|
|
2244
|
-
if (opts.project) {
|
|
2245
|
-
const
|
|
2246
|
-
if (!
|
|
2247
|
-
renderResult(opts.format,
|
|
2333
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
2334
|
+
const pr = await resolveScopedProject(client, opts.project, "explicit-only");
|
|
2335
|
+
if (!pr.success) {
|
|
2336
|
+
renderResult(opts.format, pr);
|
|
2248
2337
|
return;
|
|
2249
2338
|
}
|
|
2250
|
-
|
|
2339
|
+
const pid = pr.data.projectId;
|
|
2340
|
+
if (pid !== void 0) filters.projectId = pid;
|
|
2251
2341
|
}
|
|
2252
2342
|
if (opts.sort) {
|
|
2253
2343
|
const r = parseEnum(opts.sort, z5.enum(["progress", "createdAt", "updatedAt"]), "sort");
|
|
@@ -2303,7 +2393,7 @@ function createTaskCommand() {
|
|
|
2303
2393
|
const result = await handleQueryState(client, taskId);
|
|
2304
2394
|
renderResult(opts.format, result, { fields: result.success ? taskFields(result.data) : [] });
|
|
2305
2395
|
});
|
|
2306
|
-
task.command("create").description("Create a task from a DAG template").option("--url <url>", "server base URL").requiredOption("--title <t>", "task title").requiredOption("--template <code|name|id>", "DAG template code (preferred), name, or 24-hex id (code/name resolved within project)").requiredOption("--track <t>", "task track (e.g. backend|ui|mixed|research \u2014 research \u4E3A\u8C03\u7814\u7C7B\u578B\u4E13\u7528\uFF0C\u987B\u914D --type research)").option("--type <t>", "task type (feature|bugfix|ui-tweak|research) \u2014 \u7C7B\u578B\u2192\u8DEF\u5F84\u6620\u5C04\u7531 task-create skill \u6301\u6709").option("--skip <ids>", "node ids to prune at creation (comma-separated, repeatable) \u2014 \u53EA\u5141\u8BB8\u6765\u81EA task-create skill \u7684\u6620\u5C04\u77E9\u9635", collectArgs, []).option("--project <key
|
|
2396
|
+
task.command("create").description("Create a task from a DAG template").option("--url <url>", "server base URL").requiredOption("--title <t>", "task title").requiredOption("--template <code|name|id>", "DAG template code (preferred), name, or 24-hex id (code/name resolved within project)").requiredOption("--track <t>", "task track (e.g. backend|ui|mixed|research \u2014 research \u4E3A\u8C03\u7814\u7C7B\u578B\u4E13\u7528\uFF0C\u987B\u914D --type research)").option("--type <t>", "task type (feature|bugfix|ui-tweak|research) \u2014 \u7C7B\u578B\u2192\u8DEF\u5F84\u6620\u5C04\u7531 task-create skill \u6301\u6709").option("--skip <ids>", "node ids to prune at creation (comma-separated, repeatable) \u2014 \u53EA\u5141\u8BB8\u6765\u81EA task-create skill \u7684\u6620\u5C04\u77E9\u9635", collectArgs, []).option("--project <key|id>", "projectId (key|id; defaults to workspace defaultProject then template projectId)").action(async (opts) => {
|
|
2307
2397
|
const client = createClient(opts.url);
|
|
2308
2398
|
let type;
|
|
2309
2399
|
if (opts.type !== void 0) {
|
|
@@ -2318,21 +2408,12 @@ function createTaskCommand() {
|
|
|
2318
2408
|
if (opts.skip !== void 0 && opts.skip.length > 0) {
|
|
2319
2409
|
skipNodes = [...new Set(opts.skip.flatMap((s) => s.split(",")).map((s) => s.trim()).filter((s) => s.length > 0))];
|
|
2320
2410
|
}
|
|
2321
|
-
|
|
2322
|
-
if (
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
renderResult("json", r);
|
|
2326
|
-
return;
|
|
2327
|
-
}
|
|
2328
|
-
projectId = r.data;
|
|
2329
|
-
} else {
|
|
2330
|
-
const wsDefaultProject = readWorkspaceConfig()?.defaultProject;
|
|
2331
|
-
if (wsDefaultProject) {
|
|
2332
|
-
const r = await resolveProjectId(client, wsDefaultProject);
|
|
2333
|
-
if (r.success) projectId = r.data;
|
|
2334
|
-
}
|
|
2411
|
+
const projectR = await resolveScopedProject(client, opts.project, "ws-default", { commandLabel: "siming task create" });
|
|
2412
|
+
if (!projectR.success) {
|
|
2413
|
+
renderResult("json", projectR);
|
|
2414
|
+
return;
|
|
2335
2415
|
}
|
|
2416
|
+
const projectId = projectR.data.projectId;
|
|
2336
2417
|
let templateRef = opts.template;
|
|
2337
2418
|
if (!/^[0-9a-f]{24}$/.test(templateRef)) {
|
|
2338
2419
|
const listR = await handleListTemplates(client, projectId);
|
|
@@ -2351,20 +2432,9 @@ function createTaskCommand() {
|
|
|
2351
2432
|
...skipNodes !== void 0 && skipNodes.length > 0 ? { skipNodes } : {},
|
|
2352
2433
|
...projectId ? { projectId } : {}
|
|
2353
2434
|
});
|
|
2354
|
-
if (!result.success && !opts.project) {
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
renderResult("json", { ...result, error: { ...result.error, hint: "workspace defaultProject \u6307\u5411\u7684\u9879\u76EE\u4E0D\u5B58\u5728\u2014\u2014run `siming config unset defaultProject` or `siming config set defaultProject <key|id>`" } });
|
|
2358
|
-
return;
|
|
2359
|
-
}
|
|
2360
|
-
if (bizCode === "PROJECT_ARCHIVED") {
|
|
2361
|
-
renderResult("json", { ...result, error: { ...result.error, hint: "workspace defaultProject \u6307\u5411\u7684\u9879\u76EE\u5DF2\u5F52\u6863\u2014\u2014run `siming project list --status active` to pick an active project" } });
|
|
2362
|
-
return;
|
|
2363
|
-
}
|
|
2364
|
-
if (bizCode === "TEMPLATE_PROJECT_MISMATCH") {
|
|
2365
|
-
renderResult("json", { ...result, error: { ...result.error, hint: "template belongs to another project\u2014\u2014pass --project <key|id> of the template's project" } });
|
|
2366
|
-
return;
|
|
2367
|
-
}
|
|
2435
|
+
if (!result.success && !opts.project && result.error.bizCode === "TEMPLATE_PROJECT_MISMATCH") {
|
|
2436
|
+
renderResult("json", { ...result, error: { ...result.error, hint: "template belongs to another project\u2014\u2014pass --project <key|id> of the template's project" } });
|
|
2437
|
+
return;
|
|
2368
2438
|
}
|
|
2369
2439
|
renderResult("json", result);
|
|
2370
2440
|
});
|
|
@@ -3214,9 +3284,18 @@ async function handleScaffoldSkill(client, input) {
|
|
|
3214
3284
|
// src/commands/skill/command.ts
|
|
3215
3285
|
function createSkillCommand() {
|
|
3216
3286
|
const skill = new Command3("skill").description("Skill management \u2014 global/project-scoped skills");
|
|
3217
|
-
withCommonOpts(skill.command("list"), "table").option("--project <id>", "filter by projectId").description("List skills").action(async (opts) => {
|
|
3287
|
+
withCommonOpts(skill.command("list"), "table").option("--project <key|id>", "filter by projectId (key|id)").description("List skills").action(async (opts) => {
|
|
3218
3288
|
const client = createClient(opts.url);
|
|
3219
|
-
|
|
3289
|
+
let projectId;
|
|
3290
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
3291
|
+
const pr = await resolveScopedProject(client, opts.project, "explicit-only");
|
|
3292
|
+
if (!pr.success) {
|
|
3293
|
+
renderResult(opts.format, pr);
|
|
3294
|
+
return;
|
|
3295
|
+
}
|
|
3296
|
+
projectId = pr.data.projectId;
|
|
3297
|
+
}
|
|
3298
|
+
const result = await handleListSkills(client, projectId);
|
|
3220
3299
|
renderResult(opts.format, result, {
|
|
3221
3300
|
columns: [
|
|
3222
3301
|
{ key: "name", header: "Name" },
|
|
@@ -3228,7 +3307,7 @@ function createSkillCommand() {
|
|
|
3228
3307
|
]
|
|
3229
3308
|
});
|
|
3230
3309
|
});
|
|
3231
|
-
withCommonOpts(skill.command("show <name>"), "fancy").description("Show skill details").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <
|
|
3310
|
+
withCommonOpts(skill.command("show <name>"), "fancy").description("Show skill details").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3232
3311
|
const client = createClient(opts.url);
|
|
3233
3312
|
let scope;
|
|
3234
3313
|
if (opts.scope !== void 0) {
|
|
@@ -3239,13 +3318,23 @@ function createSkillCommand() {
|
|
|
3239
3318
|
}
|
|
3240
3319
|
scope = scopeR.data;
|
|
3241
3320
|
}
|
|
3321
|
+
let projectId;
|
|
3322
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3323
|
+
if (explicitProject !== void 0 || scope === "project") {
|
|
3324
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming skill show" });
|
|
3325
|
+
if (!pr.success) {
|
|
3326
|
+
renderResult(opts.format, pr);
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
projectId = pr.data.projectId;
|
|
3330
|
+
}
|
|
3242
3331
|
const result = await handleGetSkill(client, name, {
|
|
3243
3332
|
...scope !== void 0 ? { scope } : {},
|
|
3244
|
-
...
|
|
3333
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3245
3334
|
});
|
|
3246
3335
|
renderResult(opts.format, result, { fields: result.success ? skillFields(result.data) : [] });
|
|
3247
3336
|
});
|
|
3248
|
-
skill.command("create").description("Create a skill (scope required)").option("--url <url>", "server base URL").requiredOption("--name <name>", "skill name (kebab-case)").requiredOption("--description <text>", "skill description").requiredOption("--content <text>", "skill content (prompt body)").requiredOption("--category <cat>", "process|domain|tooling").requiredOption("--scope <scope>", "global|project").option("--ref <path@file>", "reference doc: <relative path>@<local file> (repeatable)", collectArgs, []).option("--project-id <
|
|
3337
|
+
skill.command("create").description("Create a skill (scope required)").option("--url <url>", "server base URL").requiredOption("--name <name>", "skill name (kebab-case)").requiredOption("--description <text>", "skill description").requiredOption("--content <text>", "skill content (prompt body)").requiredOption("--category <cat>", "process|domain|tooling").requiredOption("--scope <scope>", "global|project").option("--ref <path@file>", "reference doc: <relative path>@<local file> (repeatable)", collectArgs, []).option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (opts) => {
|
|
3249
3338
|
const categoryR = parseEnum(opts.category, SkillCategorySchema, "category");
|
|
3250
3339
|
if (!categoryR.success) {
|
|
3251
3340
|
renderResult("json", categoryR);
|
|
@@ -3262,6 +3351,16 @@ function createSkillCommand() {
|
|
|
3262
3351
|
return;
|
|
3263
3352
|
}
|
|
3264
3353
|
const client = createClient(opts.url);
|
|
3354
|
+
let projectId;
|
|
3355
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3356
|
+
if (explicitProject !== void 0 || scopeR.data === "project") {
|
|
3357
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming skill create" });
|
|
3358
|
+
if (!pr.success) {
|
|
3359
|
+
renderResult("json", pr);
|
|
3360
|
+
return;
|
|
3361
|
+
}
|
|
3362
|
+
projectId = pr.data.projectId;
|
|
3363
|
+
}
|
|
3265
3364
|
const input = {
|
|
3266
3365
|
name: opts.name,
|
|
3267
3366
|
description: opts.description,
|
|
@@ -3270,12 +3369,12 @@ function createSkillCommand() {
|
|
|
3270
3369
|
scope: scopeR.data,
|
|
3271
3370
|
version: "1.0.0",
|
|
3272
3371
|
...refsR.data.length > 0 ? { references: refsR.data } : {},
|
|
3273
|
-
...
|
|
3372
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3274
3373
|
};
|
|
3275
3374
|
const result = await handleCreateSkill(client, input);
|
|
3276
3375
|
renderResult("json", result);
|
|
3277
3376
|
});
|
|
3278
|
-
skill.command("update <name>").description("Update a skill (partial; references untouched unless --ref/--clear-refs given)").option("--url <url>", "server base URL").option("--description <text>", "new description").option("--content <text>", "new content").option("--new-version <v>", "new version (note: --version is reserved for the program version)").option("--scope <scope>", "global|project (asset addressing)").option("--ref <path@file>", "replace all reference docs: <relative path>@<local file> (repeatable)", collectArgs, []).option("--clear-refs", "remove all reference docs (mutually exclusive with --ref)").option("--project-id <
|
|
3377
|
+
skill.command("update <name>").description("Update a skill (partial; references untouched unless --ref/--clear-refs given)").option("--url <url>", "server base URL").option("--description <text>", "new description").option("--content <text>", "new content").option("--new-version <v>", "new version (note: --version is reserved for the program version)").option("--scope <scope>", "global|project (asset addressing)").option("--ref <path@file>", "replace all reference docs: <relative path>@<local file> (repeatable)", collectArgs, []).option("--clear-refs", "remove all reference docs (mutually exclusive with --ref)").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3279
3378
|
const client = createClient(opts.url);
|
|
3280
3379
|
let scope;
|
|
3281
3380
|
if (opts.scope !== void 0) {
|
|
@@ -3305,21 +3404,31 @@ function createSkillCommand() {
|
|
|
3305
3404
|
}
|
|
3306
3405
|
references = refsR.data;
|
|
3307
3406
|
}
|
|
3407
|
+
let projectId;
|
|
3408
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3409
|
+
if (explicitProject !== void 0 || scope === "project") {
|
|
3410
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming skill update" });
|
|
3411
|
+
if (!pr.success) {
|
|
3412
|
+
renderResult("json", pr);
|
|
3413
|
+
return;
|
|
3414
|
+
}
|
|
3415
|
+
projectId = pr.data.projectId;
|
|
3416
|
+
}
|
|
3308
3417
|
const patch = {
|
|
3309
3418
|
...opts.description !== void 0 ? { description: opts.description } : {},
|
|
3310
3419
|
...opts.content !== void 0 ? { content: opts.content } : {},
|
|
3311
3420
|
...opts.newVersion !== void 0 ? { version: opts.newVersion } : {},
|
|
3312
3421
|
...scope !== void 0 ? { scope } : {},
|
|
3313
3422
|
...references !== void 0 ? { references } : {},
|
|
3314
|
-
...
|
|
3423
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3315
3424
|
};
|
|
3316
3425
|
const result = await handleUpdateSkill(client, name, patch, {
|
|
3317
3426
|
...scope !== void 0 ? { scope } : {},
|
|
3318
|
-
...
|
|
3427
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3319
3428
|
});
|
|
3320
3429
|
renderResult("json", result);
|
|
3321
3430
|
});
|
|
3322
|
-
skill.command("copy <name>").description("Copy a skill to a new name/scope").option("--url <url>", "server base URL").requiredOption("--new-name <name>", "copy name").requiredOption("--new-scope <scope>", "global|project").option("--target-project-id <
|
|
3431
|
+
skill.command("copy <name>").description("Copy a skill to a new name/scope").option("--url <url>", "server base URL").requiredOption("--new-name <name>", "copy name").requiredOption("--new-scope <scope>", "global|project").option("--target-project-id <key|id>", "target projectId (newScope=project; falls back to workspace/instance default project)").option("--scope <scope>", "source asset addressing: global|project (defaults to global)").option("--source-project-id <key|id>", "source projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3323
3432
|
const scopeR = parseEnum(opts.newScope, SkillScopeSchema, "new-scope");
|
|
3324
3433
|
if (!scopeR.success) {
|
|
3325
3434
|
renderResult("json", scopeR);
|
|
@@ -3335,22 +3444,42 @@ function createSkillCommand() {
|
|
|
3335
3444
|
srcScope = srcR.data;
|
|
3336
3445
|
}
|
|
3337
3446
|
const client = createClient(opts.url);
|
|
3447
|
+
let targetProjectId;
|
|
3448
|
+
const explicitTarget = opts.targetProjectId !== void 0 && opts.targetProjectId.trim().length > 0 ? opts.targetProjectId : void 0;
|
|
3449
|
+
if (explicitTarget !== void 0 || scopeR.data === "project") {
|
|
3450
|
+
const pr = await resolveScopedProject(client, explicitTarget, "instance-default", { commandLabel: "siming skill copy (target)" });
|
|
3451
|
+
if (!pr.success) {
|
|
3452
|
+
renderResult("json", pr);
|
|
3453
|
+
return;
|
|
3454
|
+
}
|
|
3455
|
+
targetProjectId = pr.data.projectId;
|
|
3456
|
+
}
|
|
3457
|
+
let sourceProjectId;
|
|
3458
|
+
const explicitSource = opts.sourceProjectId !== void 0 && opts.sourceProjectId.trim().length > 0 ? opts.sourceProjectId : void 0;
|
|
3459
|
+
if (explicitSource !== void 0 || srcScope === "project") {
|
|
3460
|
+
const pr = await resolveScopedProject(client, explicitSource, "instance-default", { commandLabel: "siming skill copy (source)" });
|
|
3461
|
+
if (!pr.success) {
|
|
3462
|
+
renderResult("json", pr);
|
|
3463
|
+
return;
|
|
3464
|
+
}
|
|
3465
|
+
sourceProjectId = pr.data.projectId;
|
|
3466
|
+
}
|
|
3338
3467
|
const result = await handleCopySkill(
|
|
3339
3468
|
client,
|
|
3340
3469
|
name,
|
|
3341
3470
|
{
|
|
3342
3471
|
newName: opts.newName,
|
|
3343
3472
|
newScope: scopeR.data,
|
|
3344
|
-
...
|
|
3473
|
+
...targetProjectId !== void 0 ? { targetProjectId } : {}
|
|
3345
3474
|
},
|
|
3346
3475
|
{
|
|
3347
3476
|
...srcScope !== void 0 ? { scope: srcScope } : {},
|
|
3348
|
-
...
|
|
3477
|
+
...sourceProjectId !== void 0 ? { projectId: sourceProjectId } : {}
|
|
3349
3478
|
}
|
|
3350
3479
|
);
|
|
3351
3480
|
renderResult("json", result);
|
|
3352
3481
|
});
|
|
3353
|
-
withCommonOpts(skill.command("delete <name>"), "fancy").description("Delete a skill").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <
|
|
3482
|
+
withCommonOpts(skill.command("delete <name>"), "fancy").description("Delete a skill").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3354
3483
|
const client = createClient(opts.url);
|
|
3355
3484
|
let scope;
|
|
3356
3485
|
if (opts.scope !== void 0) {
|
|
@@ -3361,13 +3490,23 @@ function createSkillCommand() {
|
|
|
3361
3490
|
}
|
|
3362
3491
|
scope = scopeR.data;
|
|
3363
3492
|
}
|
|
3493
|
+
let projectId;
|
|
3494
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3495
|
+
if (explicitProject !== void 0 || scope === "project") {
|
|
3496
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming skill delete" });
|
|
3497
|
+
if (!pr.success) {
|
|
3498
|
+
renderResult("json", pr);
|
|
3499
|
+
return;
|
|
3500
|
+
}
|
|
3501
|
+
projectId = pr.data.projectId;
|
|
3502
|
+
}
|
|
3364
3503
|
const result = await handleDeleteSkill(client, name, {
|
|
3365
3504
|
...scope !== void 0 ? { scope } : {},
|
|
3366
|
-
...
|
|
3505
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3367
3506
|
});
|
|
3368
3507
|
renderResult(opts.format, result, { successMessage: `deleted skill '${name}'` });
|
|
3369
3508
|
});
|
|
3370
|
-
skill.command("enabled <name> <on|off>").description("Enable/disable a skill (asset addressing; defaults to global)").option("--url <url>", "server base URL").option("--format <fmt>", "output format: fancy|table|json", "fancy").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <
|
|
3509
|
+
skill.command("enabled <name> <on|off>").description("Enable/disable a skill (asset addressing; defaults to global)").option("--url <url>", "server base URL").option("--format <fmt>", "output format: fancy|table|json", "fancy").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (name, onOff, opts) => {
|
|
3371
3510
|
const enabledR = parseOnOff(onOff);
|
|
3372
3511
|
if (!enabledR.success) {
|
|
3373
3512
|
renderResult(opts.format, enabledR);
|
|
@@ -3383,9 +3522,19 @@ function createSkillCommand() {
|
|
|
3383
3522
|
}
|
|
3384
3523
|
scope = scopeR.data;
|
|
3385
3524
|
}
|
|
3525
|
+
let projectId;
|
|
3526
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3527
|
+
if (explicitProject !== void 0 || scope === "project") {
|
|
3528
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming skill enabled" });
|
|
3529
|
+
if (!pr.success) {
|
|
3530
|
+
renderResult(opts.format, pr);
|
|
3531
|
+
return;
|
|
3532
|
+
}
|
|
3533
|
+
projectId = pr.data.projectId;
|
|
3534
|
+
}
|
|
3386
3535
|
const result = await handleSetSkillEnabled(client, name, enabledR.data, {
|
|
3387
3536
|
...scope !== void 0 ? { scope } : {},
|
|
3388
|
-
...
|
|
3537
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3389
3538
|
});
|
|
3390
3539
|
renderResult(opts.format, result, {
|
|
3391
3540
|
successMessage: `skill '${name}' ${enabledR.data ? "enabled" : "disabled"}`
|
|
@@ -3393,16 +3542,17 @@ function createSkillCommand() {
|
|
|
3393
3542
|
});
|
|
3394
3543
|
skill.command("scaffold <template>").description(
|
|
3395
3544
|
"Scaffold an official project-scoped skill from the packaged skeleton (task-create entry; same-name conflict refused by default)"
|
|
3396
|
-
).option("--url <url>", "server base URL").
|
|
3545
|
+
).option("--url <url>", "server base URL").option("--project <key|id>", "target project (key|id; falls back to workspace/instance default project)").option("--overwrite", "explicitly replace an existing same-name project asset (version bumps monotonically; enabled state untouched)").option("--format <fmt>", "output format: fancy|table|json", "fancy").action(async (template, opts) => {
|
|
3397
3546
|
const client = createClient(opts.url);
|
|
3398
|
-
const projectR = await
|
|
3547
|
+
const projectR = await resolveScopedProject(client, opts.project, "instance-default", { commandLabel: "siming skill scaffold" });
|
|
3399
3548
|
if (!projectR.success) {
|
|
3400
3549
|
renderResult(opts.format, projectR);
|
|
3401
3550
|
return;
|
|
3402
3551
|
}
|
|
3403
3552
|
const result = await handleScaffoldSkill(client, {
|
|
3404
3553
|
template,
|
|
3405
|
-
projectId: projectR.data,
|
|
3554
|
+
projectId: projectR.data.projectId,
|
|
3555
|
+
// instance-default 成功必含 id
|
|
3406
3556
|
...opts.overwrite === true ? { overwrite: true } : {}
|
|
3407
3557
|
});
|
|
3408
3558
|
const renderOptions = result.success ? {
|
|
@@ -3493,9 +3643,18 @@ async function handleDeleteAgent(client, name, query = {}) {
|
|
|
3493
3643
|
// src/commands/agent/command.ts
|
|
3494
3644
|
function createAgentCommand() {
|
|
3495
3645
|
const agent = new Command4("agent").description("Agent management \u2014 subagent definitions (global/project scope)");
|
|
3496
|
-
withCommonOpts(agent.command("list"), "table").option("--project <id>", "filter by projectId").description("List agents").action(async (opts) => {
|
|
3646
|
+
withCommonOpts(agent.command("list"), "table").option("--project <key|id>", "filter by projectId (key|id)").description("List agents").action(async (opts) => {
|
|
3497
3647
|
const client = createClient(opts.url);
|
|
3498
|
-
|
|
3648
|
+
let projectId;
|
|
3649
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
3650
|
+
const pr = await resolveScopedProject(client, opts.project, "explicit-only");
|
|
3651
|
+
if (!pr.success) {
|
|
3652
|
+
renderResult(opts.format, pr);
|
|
3653
|
+
return;
|
|
3654
|
+
}
|
|
3655
|
+
projectId = pr.data.projectId;
|
|
3656
|
+
}
|
|
3657
|
+
const result = await handleListAgents(client, projectId);
|
|
3499
3658
|
renderResult(opts.format, result, {
|
|
3500
3659
|
columns: [
|
|
3501
3660
|
{ key: "name", header: "Name" },
|
|
@@ -3513,7 +3672,7 @@ function createAgentCommand() {
|
|
|
3513
3672
|
const result = await handleGetAgent(client, name);
|
|
3514
3673
|
renderResult(opts.format, result, { fields: result.success ? agentFields(result.data) : [] });
|
|
3515
3674
|
});
|
|
3516
|
-
agent.command("create").description("Create an agent (scope + system-prompt + model required)").option("--url <url>", "server base URL").requiredOption("--name <name>", "agent name").requiredOption("--description <text>", "agent description").requiredOption("--system-prompt <text>", "system prompt").requiredOption("--model <code>", "model siming-code (kebab-case)").requiredOption("--scope <scope>", "global|project").option("--function <function>", "agent function: reviewer|executor (default executor)").option("--bound-skill <name>", "bound skill name (repeatable)", collectArgs, []).option("--tool <name>", "tool name (repeatable)", collectArgs, []).option("--permission <name>", "permission name (repeatable)", collectArgs, []).option("--ref <path@file>", "reference doc: <relative path>@<local file> (repeatable)", collectArgs, []).option("--project-id <
|
|
3675
|
+
agent.command("create").description("Create an agent (scope + system-prompt + model required)").option("--url <url>", "server base URL").requiredOption("--name <name>", "agent name").requiredOption("--description <text>", "agent description").requiredOption("--system-prompt <text>", "system prompt").requiredOption("--model <code>", "model siming-code (kebab-case)").requiredOption("--scope <scope>", "global|project").option("--function <function>", "agent function: reviewer|executor (default executor)").option("--bound-skill <name>", "bound skill name (repeatable)", collectArgs, []).option("--tool <name>", "tool name (repeatable)", collectArgs, []).option("--permission <name>", "permission name (repeatable)", collectArgs, []).option("--ref <path@file>", "reference doc: <relative path>@<local file> (repeatable)", collectArgs, []).option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (opts) => {
|
|
3517
3676
|
const scopeR = parseEnum(opts.scope, AgentScopeSchema, "scope");
|
|
3518
3677
|
if (!scopeR.success) {
|
|
3519
3678
|
renderResult("json", scopeR);
|
|
@@ -3534,6 +3693,16 @@ function createAgentCommand() {
|
|
|
3534
3693
|
return;
|
|
3535
3694
|
}
|
|
3536
3695
|
const client = createClient(opts.url);
|
|
3696
|
+
let projectId;
|
|
3697
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3698
|
+
if (explicitProject !== void 0 || scopeR.data === "project") {
|
|
3699
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming agent create" });
|
|
3700
|
+
if (!pr.success) {
|
|
3701
|
+
renderResult("json", pr);
|
|
3702
|
+
return;
|
|
3703
|
+
}
|
|
3704
|
+
projectId = pr.data.projectId;
|
|
3705
|
+
}
|
|
3537
3706
|
const input = {
|
|
3538
3707
|
name: opts.name,
|
|
3539
3708
|
description: opts.description,
|
|
@@ -3547,12 +3716,12 @@ function createAgentCommand() {
|
|
|
3547
3716
|
tools: opts.tool,
|
|
3548
3717
|
permissions: opts.permission,
|
|
3549
3718
|
...refsR.data.length > 0 ? { references: refsR.data } : {},
|
|
3550
|
-
...
|
|
3719
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3551
3720
|
};
|
|
3552
3721
|
const result = await handleCreateAgent(client, input);
|
|
3553
3722
|
renderResult("json", result);
|
|
3554
3723
|
});
|
|
3555
|
-
agent.command("update <name>").description("Update an agent (partial)").option("--url <url>", "server base URL").option("--description <text>", "new description").option("--system-prompt <text>", "new system prompt").option("--model <code>", "new model siming-code").option("--scope <scope>", "global|project (asset addressing)").option("--function <function>", "new agent function: reviewer|executor").option("--bound-skill <name>", "replace bound skills (repeatable)", collectArgs, []).option("--tool <name>", "replace tools (repeatable)", collectArgs, []).option("--permission <name>", "replace permissions (repeatable)", collectArgs, []).option("--ref <path@file>", "replace all reference docs: <relative path>@<local file> (repeatable)", collectArgs, []).option("--clear-refs", "remove all reference docs (mutually exclusive with --ref)").option("--project-id <
|
|
3724
|
+
agent.command("update <name>").description("Update an agent (partial)").option("--url <url>", "server base URL").option("--description <text>", "new description").option("--system-prompt <text>", "new system prompt").option("--model <code>", "new model siming-code").option("--scope <scope>", "global|project (asset addressing)").option("--function <function>", "new agent function: reviewer|executor").option("--bound-skill <name>", "replace bound skills (repeatable)", collectArgs, []).option("--tool <name>", "replace tools (repeatable)", collectArgs, []).option("--permission <name>", "replace permissions (repeatable)", collectArgs, []).option("--ref <path@file>", "replace all reference docs: <relative path>@<local file> (repeatable)", collectArgs, []).option("--clear-refs", "remove all reference docs (mutually exclusive with --ref)").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3556
3725
|
const client = createClient(opts.url);
|
|
3557
3726
|
let scope;
|
|
3558
3727
|
if (opts.scope !== void 0) {
|
|
@@ -3591,6 +3760,16 @@ function createAgentCommand() {
|
|
|
3591
3760
|
}
|
|
3592
3761
|
references = refsR.data;
|
|
3593
3762
|
}
|
|
3763
|
+
let projectId;
|
|
3764
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3765
|
+
if (explicitProject !== void 0 || scope === "project") {
|
|
3766
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming agent update" });
|
|
3767
|
+
if (!pr.success) {
|
|
3768
|
+
renderResult("json", pr);
|
|
3769
|
+
return;
|
|
3770
|
+
}
|
|
3771
|
+
projectId = pr.data.projectId;
|
|
3772
|
+
}
|
|
3594
3773
|
const patch = {
|
|
3595
3774
|
...opts.description !== void 0 ? { description: opts.description } : {},
|
|
3596
3775
|
...opts.systemPrompt !== void 0 ? { systemPrompt: opts.systemPrompt } : {},
|
|
@@ -3601,15 +3780,15 @@ function createAgentCommand() {
|
|
|
3601
3780
|
...opts.tool.length > 0 ? { tools: opts.tool } : {},
|
|
3602
3781
|
...opts.permission.length > 0 ? { permissions: opts.permission } : {},
|
|
3603
3782
|
...references !== void 0 ? { references } : {},
|
|
3604
|
-
...
|
|
3783
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3605
3784
|
};
|
|
3606
3785
|
const result = await handleUpdateAgent(client, name, patch, {
|
|
3607
3786
|
...scope !== void 0 ? { scope } : {},
|
|
3608
|
-
...
|
|
3787
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3609
3788
|
});
|
|
3610
3789
|
renderResult("json", result);
|
|
3611
3790
|
});
|
|
3612
|
-
agent.command("copy <name>").description("Copy an agent to a new name/scope").option("--url <url>", "server base URL").requiredOption("--new-name <name>", "copy name").requiredOption("--new-scope <scope>", "global|project").option("--target-project-id <
|
|
3791
|
+
agent.command("copy <name>").description("Copy an agent to a new name/scope").option("--url <url>", "server base URL").requiredOption("--new-name <name>", "copy name").requiredOption("--new-scope <scope>", "global|project").option("--target-project-id <key|id>", "target projectId (newScope=project; falls back to workspace/instance default project)").option("--scope <scope>", "source asset addressing: global|project (defaults to global)").option("--source-project-id <key|id>", "source projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3613
3792
|
const scopeR = parseEnum(opts.newScope, AgentScopeSchema, "new-scope");
|
|
3614
3793
|
if (!scopeR.success) {
|
|
3615
3794
|
renderResult("json", scopeR);
|
|
@@ -3625,22 +3804,42 @@ function createAgentCommand() {
|
|
|
3625
3804
|
srcScope = srcR.data;
|
|
3626
3805
|
}
|
|
3627
3806
|
const client = createClient(opts.url);
|
|
3807
|
+
let targetProjectId;
|
|
3808
|
+
const explicitTarget = opts.targetProjectId !== void 0 && opts.targetProjectId.trim().length > 0 ? opts.targetProjectId : void 0;
|
|
3809
|
+
if (explicitTarget !== void 0 || scopeR.data === "project") {
|
|
3810
|
+
const pr = await resolveScopedProject(client, explicitTarget, "instance-default", { commandLabel: "siming agent copy (target)" });
|
|
3811
|
+
if (!pr.success) {
|
|
3812
|
+
renderResult("json", pr);
|
|
3813
|
+
return;
|
|
3814
|
+
}
|
|
3815
|
+
targetProjectId = pr.data.projectId;
|
|
3816
|
+
}
|
|
3817
|
+
let sourceProjectId;
|
|
3818
|
+
const explicitSource = opts.sourceProjectId !== void 0 && opts.sourceProjectId.trim().length > 0 ? opts.sourceProjectId : void 0;
|
|
3819
|
+
if (explicitSource !== void 0 || srcScope === "project") {
|
|
3820
|
+
const pr = await resolveScopedProject(client, explicitSource, "instance-default", { commandLabel: "siming agent copy (source)" });
|
|
3821
|
+
if (!pr.success) {
|
|
3822
|
+
renderResult("json", pr);
|
|
3823
|
+
return;
|
|
3824
|
+
}
|
|
3825
|
+
sourceProjectId = pr.data.projectId;
|
|
3826
|
+
}
|
|
3628
3827
|
const result = await handleCopyAgent(
|
|
3629
3828
|
client,
|
|
3630
3829
|
name,
|
|
3631
3830
|
{
|
|
3632
3831
|
newName: opts.newName,
|
|
3633
3832
|
newScope: scopeR.data,
|
|
3634
|
-
...
|
|
3833
|
+
...targetProjectId !== void 0 ? { targetProjectId } : {}
|
|
3635
3834
|
},
|
|
3636
3835
|
{
|
|
3637
3836
|
...srcScope !== void 0 ? { scope: srcScope } : {},
|
|
3638
|
-
...
|
|
3837
|
+
...sourceProjectId !== void 0 ? { projectId: sourceProjectId } : {}
|
|
3639
3838
|
}
|
|
3640
3839
|
);
|
|
3641
3840
|
renderResult("json", result);
|
|
3642
3841
|
});
|
|
3643
|
-
withCommonOpts(agent.command("delete <name>"), "fancy").description("Delete an agent").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <
|
|
3842
|
+
withCommonOpts(agent.command("delete <name>"), "fancy").description("Delete an agent").option("--scope <scope>", "global|project (asset addressing; defaults to global)").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (name, opts) => {
|
|
3644
3843
|
const client = createClient(opts.url);
|
|
3645
3844
|
let scope;
|
|
3646
3845
|
if (opts.scope !== void 0) {
|
|
@@ -3651,9 +3850,19 @@ function createAgentCommand() {
|
|
|
3651
3850
|
}
|
|
3652
3851
|
scope = scopeR.data;
|
|
3653
3852
|
}
|
|
3853
|
+
let projectId;
|
|
3854
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
3855
|
+
if (explicitProject !== void 0 || scope === "project") {
|
|
3856
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming agent delete" });
|
|
3857
|
+
if (!pr.success) {
|
|
3858
|
+
renderResult(opts.format, pr);
|
|
3859
|
+
return;
|
|
3860
|
+
}
|
|
3861
|
+
projectId = pr.data.projectId;
|
|
3862
|
+
}
|
|
3654
3863
|
const result = await handleDeleteAgent(client, name, {
|
|
3655
3864
|
...scope !== void 0 ? { scope } : {},
|
|
3656
|
-
...
|
|
3865
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
3657
3866
|
});
|
|
3658
3867
|
renderResult(opts.format, result, { successMessage: `deleted agent '${name}'` });
|
|
3659
3868
|
});
|
|
@@ -3684,23 +3893,13 @@ function createDagCommand() {
|
|
|
3684
3893
|
const tpl = dag.command("template").description("DAG template management");
|
|
3685
3894
|
withCommonOpts(tpl.command("list"), "table").option("--project <key|id>", "filter by project (key or id; defaults to workspace defaultProject)").description("List DAG templates (summary projection: node labels only, no prompts \u2014 use `show` for full detail)").action(async (opts) => {
|
|
3686
3895
|
const client = createClient(opts.url);
|
|
3687
|
-
const
|
|
3688
|
-
|
|
3689
|
-
if (
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
if (opts.project === void 0) {
|
|
3693
|
-
renderResult(opts.format, fail({
|
|
3694
|
-
...r.error,
|
|
3695
|
-
hint: `workspace defaultProject "${projectOpt}" \u89E3\u6790\u5931\u8D25\u2014\u2014siming config unset defaultProject \u540E\u91CD\u8BD5\uFF0C\u6216\u663E\u5F0F --project <key|id>`
|
|
3696
|
-
}));
|
|
3697
|
-
} else {
|
|
3698
|
-
renderResult(opts.format, r);
|
|
3699
|
-
}
|
|
3700
|
-
return;
|
|
3701
|
-
}
|
|
3702
|
-
projectId = r.data;
|
|
3896
|
+
const explicitProject = opts.project !== void 0 && opts.project.trim().length > 0 ? opts.project : void 0;
|
|
3897
|
+
const pr = await resolveScopedProject(client, explicitProject, "ws-default", { commandLabel: "siming dag template list" });
|
|
3898
|
+
if (!pr.success) {
|
|
3899
|
+
renderResult(opts.format, pr);
|
|
3900
|
+
return;
|
|
3703
3901
|
}
|
|
3902
|
+
const projectId = pr.data.projectId;
|
|
3704
3903
|
const result = await handleListTemplates(client, projectId);
|
|
3705
3904
|
if (!result.success) {
|
|
3706
3905
|
renderResult(opts.format, result);
|
|
@@ -3728,15 +3927,13 @@ function createDagCommand() {
|
|
|
3728
3927
|
const client = createClient(opts.url);
|
|
3729
3928
|
let projectId;
|
|
3730
3929
|
if (!/^[a-f0-9]{24}$/.test(templateRef)) {
|
|
3731
|
-
const
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
return;
|
|
3737
|
-
}
|
|
3738
|
-
projectId = r.data;
|
|
3930
|
+
const explicitProject = opts.project !== void 0 && opts.project.trim().length > 0 ? opts.project : void 0;
|
|
3931
|
+
const pr = await resolveScopedProject(client, explicitProject, "ws-default", { commandLabel: "siming dag template show" });
|
|
3932
|
+
if (!pr.success) {
|
|
3933
|
+
renderResult(opts.format, pr);
|
|
3934
|
+
return;
|
|
3739
3935
|
}
|
|
3936
|
+
projectId = pr.data.projectId;
|
|
3740
3937
|
}
|
|
3741
3938
|
const result = await handleGetTemplate(client, templateRef, projectId);
|
|
3742
3939
|
renderResult(opts.format, result, { fields: result.success ? templateFields(result.data) : [] });
|
|
@@ -3903,13 +4100,15 @@ async function runYamlImport(client, yamlText, opts, jsonParseError2) {
|
|
|
3903
4100
|
return;
|
|
3904
4101
|
}
|
|
3905
4102
|
let projectId;
|
|
3906
|
-
if (opts.project !== void 0) {
|
|
3907
|
-
const r = await
|
|
4103
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
4104
|
+
const r = await resolveScopedProject(client, opts.project, "explicit-only", {
|
|
4105
|
+
commandLabel: "siming dag template import"
|
|
4106
|
+
});
|
|
3908
4107
|
if (!r.success) {
|
|
3909
4108
|
renderResult("json", r);
|
|
3910
4109
|
return;
|
|
3911
4110
|
}
|
|
3912
|
-
projectId = r.data;
|
|
4111
|
+
projectId = r.data.projectId;
|
|
3913
4112
|
}
|
|
3914
4113
|
const result = await importTemplateFromYaml(client, yamlText, {
|
|
3915
4114
|
...projectId !== void 0 ? { projectId } : {},
|
|
@@ -3969,13 +4168,15 @@ async function runBundleImport(client, bundleText, opts) {
|
|
|
3969
4168
|
}));
|
|
3970
4169
|
return;
|
|
3971
4170
|
}
|
|
3972
|
-
const
|
|
3973
|
-
|
|
3974
|
-
|
|
4171
|
+
const explicitBundleTarget = opts.project !== void 0 && opts.project.trim().length > 0 ? opts.project : void 0;
|
|
4172
|
+
const pr = await resolveScopedProject(client, explicitBundleTarget, "instance-default", { commandLabel: "siming dag template import" });
|
|
4173
|
+
if (!pr.success) {
|
|
4174
|
+
renderResult("json", pr);
|
|
3975
4175
|
return;
|
|
3976
4176
|
}
|
|
3977
4177
|
const result = await importTemplateBundle(client, bundleText, {
|
|
3978
|
-
targetProjectId:
|
|
4178
|
+
targetProjectId: pr.data.projectId,
|
|
4179
|
+
// instance-default 成功必含 id
|
|
3979
4180
|
...opts.overwriteDeps === true ? { overwriteDeps: true } : {},
|
|
3980
4181
|
...opts.plan === true ? { planOnly: true } : {}
|
|
3981
4182
|
});
|
|
@@ -3985,31 +4186,6 @@ async function runBundleImport(client, bundleText, opts) {
|
|
|
3985
4186
|
}
|
|
3986
4187
|
renderBundleImportOutcome(result.data, opts.plan === true);
|
|
3987
4188
|
}
|
|
3988
|
-
async function resolveImportTargetProject(client, projectOpt) {
|
|
3989
|
-
if (projectOpt !== void 0) return resolveProjectId(client, projectOpt);
|
|
3990
|
-
const wsDefault = readWorkspaceConfig()?.defaultProject;
|
|
3991
|
-
if (wsDefault !== void 0) {
|
|
3992
|
-
const r = await resolveProjectId(client, wsDefault);
|
|
3993
|
-
if (!r.success) {
|
|
3994
|
-
return fail({
|
|
3995
|
-
...r.error,
|
|
3996
|
-
hint: `workspace defaultProject "${wsDefault}" \u89E3\u6790\u5931\u8D25\u2014\u2014siming config unset defaultProject \u540E\u91CD\u8BD5\uFF0C\u6216\u663E\u5F0F --project <key|id>`
|
|
3997
|
-
});
|
|
3998
|
-
}
|
|
3999
|
-
return r;
|
|
4000
|
-
}
|
|
4001
|
-
const list = await handleListProjects(client);
|
|
4002
|
-
if (!list.success) return list;
|
|
4003
|
-
const defaultProject = list.data.find((p) => p.key === "default");
|
|
4004
|
-
if (defaultProject?.id === void 0) {
|
|
4005
|
-
return fail({
|
|
4006
|
-
message: "bundle \u5BFC\u5165\u9700\u8981\u76EE\u6807\u9879\u76EE\uFF1A\u672A\u6307\u5B9A --project\uFF0C\u5DE5\u4F5C\u533A\u65E0 defaultProject\uFF0C\u5B9E\u4F8B\u4E2D\u4E5F\u65E0 key=default \u7684\u9879\u76EE",
|
|
4007
|
-
httpStatus: 0,
|
|
4008
|
-
hint: "pass --project <key|id>\uFF0C\u6216\u5148 siming project create + siming init --project <key>"
|
|
4009
|
-
});
|
|
4010
|
-
}
|
|
4011
|
-
return { success: true, data: defaultProject.id };
|
|
4012
|
-
}
|
|
4013
4189
|
function renderBundleImportOutcome(outcome, planOnly) {
|
|
4014
4190
|
const t = outcome.plan.template;
|
|
4015
4191
|
const overwritten = t.willOverwrite && t.currentVersion !== void 0 ? `\u8986\u76D6\u73B0\u6709 v${t.currentVersion} \u2192 ` : "";
|
|
@@ -4284,7 +4460,7 @@ ${failures.join("\n")}`,
|
|
|
4284
4460
|
// src/commands/node/command.ts
|
|
4285
4461
|
function createNodeCommand() {
|
|
4286
4462
|
const node = new Command6("node").description("NodePreset management \u2014 reusable DAG node assets (addressed by unique code)");
|
|
4287
|
-
withCommonOpts(node.command("list"), "table").option("--project <id>", "overlay visible set: global + this project").option("--scope <scope>", "exact scope filter: global|project").option("--q <keyword>", "search in code/label").description("List node presets (summary projection: no prompt \u2014 use `show` for full detail)").action(async (opts) => {
|
|
4463
|
+
withCommonOpts(node.command("list"), "table").option("--project <key|id>", "overlay visible set: global + this project (key|id)").option("--scope <scope>", "exact scope filter: global|project").option("--q <keyword>", "search in code/label").description("List node presets (summary projection: no prompt \u2014 use `show` for full detail)").action(async (opts) => {
|
|
4288
4464
|
let scope;
|
|
4289
4465
|
if (opts.scope !== void 0) {
|
|
4290
4466
|
const scopeR = parseEnum(opts.scope, SkillScopeSchema2, "scope");
|
|
@@ -4295,8 +4471,17 @@ function createNodeCommand() {
|
|
|
4295
4471
|
scope = scopeR.data;
|
|
4296
4472
|
}
|
|
4297
4473
|
const client = createClient(opts.url);
|
|
4474
|
+
let projectId;
|
|
4475
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
4476
|
+
const pr = await resolveScopedProject(client, opts.project, "explicit-only");
|
|
4477
|
+
if (!pr.success) {
|
|
4478
|
+
renderResult(opts.format, pr);
|
|
4479
|
+
return;
|
|
4480
|
+
}
|
|
4481
|
+
projectId = pr.data.projectId;
|
|
4482
|
+
}
|
|
4298
4483
|
const result = await handleListNodePresets(client, {
|
|
4299
|
-
...
|
|
4484
|
+
...projectId !== void 0 ? { projectId } : {},
|
|
4300
4485
|
...scope !== void 0 ? { scope } : {},
|
|
4301
4486
|
...opts.q !== void 0 ? { q: opts.q } : {}
|
|
4302
4487
|
});
|
|
@@ -4319,7 +4504,7 @@ function createNodeCommand() {
|
|
|
4319
4504
|
const result = await handleGetNodePreset(client, code);
|
|
4320
4505
|
renderResult(opts.format, result, { fields: result.success ? nodeFields2(result.data) : [] });
|
|
4321
4506
|
});
|
|
4322
|
-
node.command("create").description("Create a node preset (code globally unique & immutable; scope required)").option("--url <url>", "server base URL").requiredOption("--code <code>", "unique business code (kebab-case, immutable)").requiredOption("--label <text>", "display label").requiredOption("--node-id <id>", "default node id when assembled into templates ([A-Za-z0-9_-]+)").requiredOption("--phase <phase>", "node phase (e.g. entry|track|test|exit)").requiredOption("--track <track>", "node track (backend|ui|all)").requiredOption("--prompt <text>", "node prompt body").option("--prompt-file <path>", "read prompt from file (overrides --prompt)").option("--skill <name>", "bound skill name (repeatable)", collectArgs, []).option("--agent <name>", "callable agent name (repeatable)", collectArgs, []).option("--description <text>", "asset description").requiredOption("--scope <scope>", "global|project").option("--project-id <
|
|
4507
|
+
node.command("create").description("Create a node preset (code globally unique & immutable; scope required)").option("--url <url>", "server base URL").requiredOption("--code <code>", "unique business code (kebab-case, immutable)").requiredOption("--label <text>", "display label").requiredOption("--node-id <id>", "default node id when assembled into templates ([A-Za-z0-9_-]+)").requiredOption("--phase <phase>", "node phase (e.g. entry|track|test|exit)").requiredOption("--track <track>", "node track (backend|ui|all)").requiredOption("--prompt <text>", "node prompt body").option("--prompt-file <path>", "read prompt from file (overrides --prompt)").option("--skill <name>", "bound skill name (repeatable)", collectArgs, []).option("--agent <name>", "callable agent name (repeatable)", collectArgs, []).option("--description <text>", "asset description").requiredOption("--scope <scope>", "global|project").option("--project-id <key|id>", "projectId (scope=project; falls back to workspace/instance default project)").action(async (opts) => {
|
|
4323
4508
|
const scopeR = parseEnum(opts.scope, SkillScopeSchema2, "scope");
|
|
4324
4509
|
if (!scopeR.success) {
|
|
4325
4510
|
renderResult("json", scopeR);
|
|
@@ -4342,6 +4527,16 @@ function createNodeCommand() {
|
|
|
4342
4527
|
return;
|
|
4343
4528
|
}
|
|
4344
4529
|
const client = createClient(opts.url);
|
|
4530
|
+
let projectId;
|
|
4531
|
+
const explicitProject = opts.projectId !== void 0 && opts.projectId.trim().length > 0 ? opts.projectId : void 0;
|
|
4532
|
+
if (explicitProject !== void 0 || scopeR.data === "project") {
|
|
4533
|
+
const pr = await resolveScopedProject(client, explicitProject, "instance-default", { commandLabel: "siming node create" });
|
|
4534
|
+
if (!pr.success) {
|
|
4535
|
+
renderResult("json", pr);
|
|
4536
|
+
return;
|
|
4537
|
+
}
|
|
4538
|
+
projectId = pr.data.projectId;
|
|
4539
|
+
}
|
|
4345
4540
|
const input = {
|
|
4346
4541
|
code: opts.code,
|
|
4347
4542
|
label: opts.label,
|
|
@@ -4354,7 +4549,7 @@ function createNodeCommand() {
|
|
|
4354
4549
|
scope: scopeR.data,
|
|
4355
4550
|
version: "1.0.0",
|
|
4356
4551
|
...opts.description !== void 0 ? { description: opts.description } : {},
|
|
4357
|
-
...
|
|
4552
|
+
...projectId !== void 0 ? { projectId } : {}
|
|
4358
4553
|
};
|
|
4359
4554
|
renderResult("json", await handleCreateNodePreset(client, input));
|
|
4360
4555
|
});
|
|
@@ -4399,17 +4594,27 @@ function createNodeCommand() {
|
|
|
4399
4594
|
}
|
|
4400
4595
|
renderResult("json", await handleUpdateNodePreset(client, code, patch));
|
|
4401
4596
|
});
|
|
4402
|
-
node.command("copy <code>").description("Copy a node preset to a new code/scope (copy version resets 1.0.0)").option("--url <url>", "server base URL").requiredOption("--new-code <code>", "new unique code (kebab-case)").requiredOption("--new-scope <scope>", "global|project").option("--target-project-id <
|
|
4597
|
+
node.command("copy <code>").description("Copy a node preset to a new code/scope (copy version resets 1.0.0)").option("--url <url>", "server base URL").requiredOption("--new-code <code>", "new unique code (kebab-case)").requiredOption("--new-scope <scope>", "global|project").option("--target-project-id <key|id>", "target projectId (newScope=project; falls back to workspace/instance default project)").action(async (code, opts) => {
|
|
4403
4598
|
const scopeR = parseEnum(opts.newScope, SkillScopeSchema2, "new-scope");
|
|
4404
4599
|
if (!scopeR.success) {
|
|
4405
4600
|
renderResult("json", scopeR);
|
|
4406
4601
|
return;
|
|
4407
4602
|
}
|
|
4408
4603
|
const client = createClient(opts.url);
|
|
4604
|
+
let targetProjectId;
|
|
4605
|
+
const explicitTarget = opts.targetProjectId !== void 0 && opts.targetProjectId.trim().length > 0 ? opts.targetProjectId : void 0;
|
|
4606
|
+
if (explicitTarget !== void 0 || scopeR.data === "project") {
|
|
4607
|
+
const pr = await resolveScopedProject(client, explicitTarget, "instance-default", { commandLabel: "siming node copy" });
|
|
4608
|
+
if (!pr.success) {
|
|
4609
|
+
renderResult("json", pr);
|
|
4610
|
+
return;
|
|
4611
|
+
}
|
|
4612
|
+
targetProjectId = pr.data.projectId;
|
|
4613
|
+
}
|
|
4409
4614
|
renderResult("json", await handleCopyNodePreset(client, code, {
|
|
4410
4615
|
newCode: opts.newCode,
|
|
4411
4616
|
newScope: scopeR.data,
|
|
4412
|
-
...
|
|
4617
|
+
...targetProjectId !== void 0 ? { targetProjectId } : {}
|
|
4413
4618
|
}));
|
|
4414
4619
|
});
|
|
4415
4620
|
node.command("enabled <code>").description("Enable/disable a node preset (sole write entry for enabled; disabled presets invisible to list/compose)").option("--url <url>", "server base URL").requiredOption("--value <bool>", "true|false").action(async (code, opts) => {
|
|
@@ -4792,26 +4997,22 @@ function createFlowCommand() {
|
|
|
4792
4997
|
});
|
|
4793
4998
|
flow.command("install <pkg-spec>").description(
|
|
4794
4999
|
"Install a node library package from npm \u2014 validate 1.1 manifest \u2192 plan complete assets \u2192 confirm \u2192 apply dependencies \u2192 nodes \u2192 library"
|
|
4795
|
-
).option("--url <url>", "server base URL").option("--scope <scope>", "install scope: global|project", "global").option("--project <key|id>", "target project (
|
|
5000
|
+
).option("--url <url>", "server base URL").option("--scope <scope>", "install scope: global|project", "global").option("--project <key|id>", "target project (scope=project; falls back to workspace/instance default project)").option("--registry <url>", "npm registry for pack (e.g. private mirror; default npm config)").option("--yes", "skip interactive confirmation").option("--force", "allow version downgrade; admin may also sync a conflicting model alias display name (realModel is never overwritten)").action(async (pkgSpec, opts) => {
|
|
4796
5001
|
const scopeResult = parseEnum(opts.scope, SkillScopeSchema3, "scope");
|
|
4797
5002
|
if (!scopeResult.success) {
|
|
4798
5003
|
renderResult("json", scopeResult);
|
|
4799
5004
|
return;
|
|
4800
5005
|
}
|
|
4801
5006
|
const scope = scopeResult.data;
|
|
4802
|
-
if (scope === "project" && opts.project === void 0) {
|
|
4803
|
-
renderResult("json", fail({ message: "scope=project \u9700\u8981 --project <key|id>", httpStatus: 0 }));
|
|
4804
|
-
return;
|
|
4805
|
-
}
|
|
4806
5007
|
const client = createClient(opts.url);
|
|
4807
5008
|
let projectId;
|
|
4808
5009
|
if (scope === "project") {
|
|
4809
|
-
const
|
|
4810
|
-
if (!
|
|
4811
|
-
renderResult("json",
|
|
5010
|
+
const pr = await resolveScopedProject(client, opts.project, "instance-default", { commandLabel: "siming flow install" });
|
|
5011
|
+
if (!pr.success) {
|
|
5012
|
+
renderResult("json", pr);
|
|
4812
5013
|
return;
|
|
4813
5014
|
}
|
|
4814
|
-
projectId =
|
|
5015
|
+
projectId = pr.data.projectId;
|
|
4815
5016
|
}
|
|
4816
5017
|
const fetched = await fetchManifest(pkgSpec, opts.registry);
|
|
4817
5018
|
if (!fetched.success) {
|
|
@@ -4855,15 +5056,16 @@ ${conflicts.map((item) => ` ${item.kind}:${item.key} \u2014 ${item.reason ?? "\
|
|
|
4855
5056
|
cleanup();
|
|
4856
5057
|
}
|
|
4857
5058
|
});
|
|
4858
|
-
flow.command("compose <composition>").description("Assemble a DAG template from an installed library composition (value-copy nodes + sourcePreset baseline)").option("--url <url>", "server base URL").
|
|
5059
|
+
flow.command("compose <composition>").description("Assemble a DAG template from an installed library composition (value-copy nodes + sourcePreset baseline)").option("--url <url>", "server base URL").option("--project <key|id>", "target project (template owner; falls back to workspace/instance default project)").option("--name <name>", "generated template name (default: composition name)").option("--from <library>", "source library name (required when multiple libraries define the same composition)").action(async (composition, opts) => {
|
|
4859
5060
|
const client = createClient(opts.url);
|
|
4860
|
-
const
|
|
4861
|
-
if (!
|
|
4862
|
-
renderResult("json",
|
|
5061
|
+
const pr = await resolveScopedProject(client, opts.project, "instance-default", { commandLabel: "siming flow compose" });
|
|
5062
|
+
if (!pr.success) {
|
|
5063
|
+
renderResult("json", pr);
|
|
4863
5064
|
return;
|
|
4864
5065
|
}
|
|
4865
5066
|
const result = await composeFlowTemplate(client, composition, {
|
|
4866
|
-
projectId:
|
|
5067
|
+
projectId: pr.data.projectId,
|
|
5068
|
+
// instance-default 成功必含 id
|
|
4867
5069
|
...opts.name !== void 0 ? { name: opts.name } : {},
|
|
4868
5070
|
...opts.from !== void 0 ? { from: opts.from } : {}
|
|
4869
5071
|
});
|
|
@@ -6933,13 +7135,13 @@ function parseVersion(v) {
|
|
|
6933
7135
|
// src/commands/install/command.ts
|
|
6934
7136
|
function createInstallCommand() {
|
|
6935
7137
|
const install = new Command12("install").description("Install skills/agents from Siming to local AI platform");
|
|
6936
|
-
withCommonOpts(install.command("plan"), "table").option("--scope <s>", "install scope: global|project", "global").option("--project <key
|
|
7138
|
+
withCommonOpts(install.command("plan"), "table").option("--scope <s>", "install scope: global|project", "global").option("--project <key|id>", "project key or id (scope=project; falls back to workspace/instance default project)").option("--only <name>", 'filter by asset name (repeatable; use "siming" for the MCP entry)', collectArgs, []).description("Preview install plan (no write)").action(async (opts) => {
|
|
6937
7139
|
const scope = parseScope(opts.scope, opts.format);
|
|
6938
7140
|
if (!scope) return;
|
|
6939
7141
|
const client = createClient(opts.url);
|
|
6940
7142
|
const projectR = await resolveInstallProject(client, scope, opts.project);
|
|
6941
7143
|
if (!projectR.ok) {
|
|
6942
|
-
renderResult(opts.format, { success: false, error: { message: projectR.error.message, httpStatus: 0, ...projectR.error.hint ? { hint: projectR.error.hint } : {} } });
|
|
7144
|
+
renderResult(opts.format, { success: false, error: { message: projectR.error.message, httpStatus: projectR.error.httpStatus, ...projectR.error.bizCode !== void 0 ? { bizCode: projectR.error.bizCode } : {}, ...projectR.error.hint ? { hint: projectR.error.hint } : {} } });
|
|
6943
7145
|
return;
|
|
6944
7146
|
}
|
|
6945
7147
|
const projectId = projectR.projectId;
|
|
@@ -6951,14 +7153,14 @@ function createInstallCommand() {
|
|
|
6951
7153
|
const plan = result.data;
|
|
6952
7154
|
renderInstallPlan2(opts.format, plan, scope, resolveInstallTargets(scope).targets);
|
|
6953
7155
|
});
|
|
6954
|
-
withCommonOpts(install.command("apply"), "json").option("--scope <s>", "install scope: global|project", "global").option("--project <key
|
|
7156
|
+
withCommonOpts(install.command("apply"), "json").option("--scope <s>", "install scope: global|project", "global").option("--project <key|id>", "project key or id (scope=project; falls back to workspace/instance default project)").option("--only <name>", 'install only this asset (repeatable; use "siming" for the MCP entry)', collectArgs, []).option("--yes", "skip interactive confirmation").option("--force", "overwrite all selected local assets, including same-version and conflict items").description("Apply install plan (write to local)").action(
|
|
6955
7157
|
async (opts) => {
|
|
6956
7158
|
const scope = parseScope(opts.scope, opts.format);
|
|
6957
7159
|
if (!scope) return;
|
|
6958
7160
|
const client = createClient(opts.url);
|
|
6959
7161
|
const projectR = await resolveInstallProject(client, scope, opts.project);
|
|
6960
7162
|
if (!projectR.ok) {
|
|
6961
|
-
renderResult(opts.format, { success: false, error: { message: projectR.error.message, httpStatus: 0, ...projectR.error.hint ? { hint: projectR.error.hint } : {} } });
|
|
7163
|
+
renderResult(opts.format, { success: false, error: { message: projectR.error.message, httpStatus: projectR.error.httpStatus, ...projectR.error.bizCode !== void 0 ? { bizCode: projectR.error.bizCode } : {}, ...projectR.error.hint ? { hint: projectR.error.hint } : {} } });
|
|
6962
7164
|
return;
|
|
6963
7165
|
}
|
|
6964
7166
|
const projectId = projectR.projectId;
|
|
@@ -7034,34 +7236,19 @@ function parseScope(s, format) {
|
|
|
7034
7236
|
}
|
|
7035
7237
|
async function resolveInstallProject(client, scope, projectOpt) {
|
|
7036
7238
|
if (scope === "global") return { ok: true };
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
if (r.success) return { ok: true, projectId: r.data };
|
|
7049
|
-
return { ok: false, error: { message: r.error.message, ...r.error.hint ? { hint: r.error.hint } : {} } };
|
|
7050
|
-
}
|
|
7051
|
-
return {
|
|
7052
|
-
ok: false,
|
|
7053
|
-
error: {
|
|
7054
|
-
message: "scope=project requires --project <key|id> or workspace default project",
|
|
7055
|
-
hint: "run `siming config set defaultProject <key|id>` or `siming install --scope project --project <key|id>`"
|
|
7056
|
-
}
|
|
7057
|
-
};
|
|
7058
|
-
}
|
|
7059
|
-
function readWorkspaceConfigSafe(ws) {
|
|
7060
|
-
try {
|
|
7061
|
-
return readWorkspaceConfig(ws);
|
|
7062
|
-
} catch {
|
|
7063
|
-
return null;
|
|
7239
|
+
const r = await resolveScopedProject(client, projectOpt, "instance-default", { commandLabel: "siming install" });
|
|
7240
|
+
if (!r.success) {
|
|
7241
|
+
return {
|
|
7242
|
+
ok: false,
|
|
7243
|
+
error: {
|
|
7244
|
+
message: r.error.message,
|
|
7245
|
+
httpStatus: r.error.httpStatus,
|
|
7246
|
+
...r.error.bizCode !== void 0 ? { bizCode: r.error.bizCode } : {},
|
|
7247
|
+
...r.error.hint ? { hint: r.error.hint } : {}
|
|
7248
|
+
}
|
|
7249
|
+
};
|
|
7064
7250
|
}
|
|
7251
|
+
return r.data.projectId !== void 0 ? { ok: true, projectId: r.data.projectId } : { ok: true };
|
|
7065
7252
|
}
|
|
7066
7253
|
async function buildInstallPlan(client, scope, projectId, only) {
|
|
7067
7254
|
const listQuery = scope === "global" ? { scope: "global", includeDisabled: true } : { scope: "project", ...projectId ? { projectId } : {}, includeDisabled: true };
|
|
@@ -7071,7 +7258,15 @@ async function buildInstallPlan(client, scope, projectId, only) {
|
|
|
7071
7258
|
if (!agentsR.success) return agentsR;
|
|
7072
7259
|
const t = resolveInstallTargets(scope);
|
|
7073
7260
|
if (t.error || !t.targets) {
|
|
7074
|
-
return {
|
|
7261
|
+
return {
|
|
7262
|
+
success: false,
|
|
7263
|
+
error: {
|
|
7264
|
+
message: t.error ?? "cannot resolve install targets",
|
|
7265
|
+
httpStatus: 0,
|
|
7266
|
+
// T202609190002:错误四要素契约补齐(hint 缺失导致 E2E_CLI_WS_INSTALL_002 失败)
|
|
7267
|
+
hint: "run `siming init --project <key|id>` inside the project workspace (containing .siming/), or retry with --scope global"
|
|
7268
|
+
}
|
|
7269
|
+
};
|
|
7075
7270
|
}
|
|
7076
7271
|
const dir = t.targets.dir;
|
|
7077
7272
|
const items = [];
|
|
@@ -7431,7 +7626,7 @@ async function runInit(client, input) {
|
|
|
7431
7626
|
};
|
|
7432
7627
|
}
|
|
7433
7628
|
function createInitCommand() {
|
|
7434
|
-
const init = new Command13("init").description("Initialize workspace config for Siming (idempotent)").option("--url <url>", "server base URL (also used to resolve project key)").option("--server-url <url>", "server base URL to persist into workspace config").option("--project <key
|
|
7629
|
+
const init = new Command13("init").description("Initialize workspace config for Siming (idempotent)").option("--url <url>", "server base URL (also used to resolve project key)").option("--server-url <url>", "server base URL to persist into workspace config").option("--project <key|id>", "project key or id to set as workspace default project").option("--install", "run install apply after init (non-interactive; writes to .agents universal dir)").option("--install-scope <scope>", "install scope when --install: global|project (default: global; global also registers mcp.json)").option("--format <fmt>", "output format", "fancy").action(async (opts) => {
|
|
7435
7630
|
const client = createClient(opts.url);
|
|
7436
7631
|
const result = await runInit(client, {
|
|
7437
7632
|
...opts.serverUrl ? { serverUrl: opts.serverUrl } : {},
|
|
@@ -7744,7 +7939,7 @@ ${ROADMAP_TEXT}
|
|
|
7744
7939
|
\u9879\u76EE\u6807\u8BC6\u3001\u5FEB\u901F\u901A\u9053\u89C4\u5219\uFF09\uFF0C\u6309\u6E05\u5355\u66FF\u6362\u4E3A\u9879\u76EE\u771F\u5B9E\u7EA6\u5B9A\u540E\u65B9\u53EF\u7528\u4E8E\u521B\u5EFA\u4EFB\u52A1\u3002
|
|
7745
7940
|
\u540C\u540D\u51B2\u7A81\u4FDD\u62A4\uFF1A\u9879\u76EE\u5185\u5DF2\u6709\u540C\u540D\u8D44\u4EA7\u65F6\u9ED8\u8BA4\u62D2\u7EDD\u4E14\u96F6\u5199\u5165\uFF1B
|
|
7746
7941
|
\u786E\u8BA4\u66FF\u6362\u52A0 --overwrite\uFF08\u7248\u672C\u5355\u8C03\u9012\u589E\uFF0C\u542F\u505C\u72B6\u6001\u4E0D\u53D8\uFF09\u3002
|
|
7747
|
-
\u67E5\u770B\u73B0\u5B58\u8D44\u4EA7\uFF1Asiming skill show task-create --scope project --project-id <id>
|
|
7942
|
+
\u67E5\u770B\u73B0\u5B58\u8D44\u4EA7\uFF1Asiming skill show task-create --scope project --project-id <key|id>
|
|
7748
7943
|
|
|
7749
7944
|
2. siming-arch \u2014\u2014 \u67B6\u6784\u6587\u6863\u7D22\u5F15\uFF1A\u6307\u5411\u672C\u9879\u76EE\u4ED3\u5E93\u67B6\u6784\u6587\u6863\u76EE\u5F55\u7684\u9AA8\u67B6
|
|
7750
7945
|
\uFF08\u6BCF\u9879\u76EE\u4E00\u4EFD\uFF1B\u67B6\u6784\u6587\u6863\u5B9E\u4F53\u5B58\u9879\u76EE\u4ED3\u5E93\uFF0C\u7D22\u5F15\u53EA\u5B58\u4F4D\u7F6E\u4E0D\u5B58\u5185\u5BB9\uFF09\u3002
|
|
@@ -8523,7 +8718,7 @@ function parseDeclarationsMap(spec) {
|
|
|
8523
8718
|
}
|
|
8524
8719
|
function createIssueCommand() {
|
|
8525
8720
|
const issue = new Command18("issue").description("Issue pool: record \u2192 organize \u2192 convert to tasks");
|
|
8526
|
-
withCommonOpts(issue.command("add"), "fancy").description("Record an issue into the pool (source=cli)").argument("[title]", "issue title (or use --title)").option("--title <t>", "issue title (1-200 chars)").option("--description <d>", "issue description (optional)").option("--project <key
|
|
8721
|
+
withCommonOpts(issue.command("add"), "fancy").description("Record an issue into the pool (source=cli; requires --approved human approval quote)").argument("[title]", "issue title (or use --title)").option("--title <t>", "issue title (1-200 chars)").option("--description <d>", "issue description (optional)").option("--approved <text>", `human approval quote verbatim (1-500 chars; e.g. user's literal reply "OK, record it")`).option("--project <key|id>", "projectId (key|id; falls back to workspace defaultProject, then server default project)").action(async (titleArg, opts) => {
|
|
8527
8722
|
const client = createClient(opts.url);
|
|
8528
8723
|
const title = opts.title ?? titleArg;
|
|
8529
8724
|
if (title === void 0 || title.length === 0) {
|
|
@@ -8533,29 +8728,41 @@ function createIssueCommand() {
|
|
|
8533
8728
|
});
|
|
8534
8729
|
return;
|
|
8535
8730
|
}
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8731
|
+
if (opts.approved === void 0 || opts.approved.trim() === "") {
|
|
8732
|
+
renderResult("json", {
|
|
8733
|
+
success: false,
|
|
8734
|
+
error: {
|
|
8735
|
+
message: 'issue add \u987B\u643A\u5E26 --approved "<\u4EBA\u7C7B\u5BA1\u6279\u539F\u8BDD>"\uFF08\u5982\u7528\u6237\u56DE\u590D\u7684\u300COK\uFF0C\u8BB0\u5F55\u300D\u539F\u6587\u9010\u5B57\uFF09\u2014\u2014AI \u4E0D\u5F97\u672A\u7ECF\u7528\u6237\u6279\u51C6\u5F55\u5165 issue\uFF0C\u4E5F\u4E0D\u5F97\u4EE3\u586B/\u7F16\u9020\u5BA1\u6279\u539F\u8BDD',
|
|
8736
|
+
httpStatus: 0
|
|
8737
|
+
}
|
|
8738
|
+
});
|
|
8739
|
+
return;
|
|
8740
|
+
}
|
|
8741
|
+
if (opts.approved.length > 500) {
|
|
8742
|
+
renderResult("json", {
|
|
8743
|
+
success: false,
|
|
8744
|
+
error: {
|
|
8745
|
+
message: `--approved \u8D85\u51FA 500 \u5B57\u4E0A\u9650\uFF08\u5F53\u524D ${String(opts.approved.length)} \u5B57\uFF09\u2014\u2014\u5BA1\u6279\u539F\u8BDD\u987B\u4E3A\u7528\u6237\u539F\u6587\u4E14 \u2264500 \u5B57\uFF0C\u53EF\u8BF7\u7528\u6237\u7ED9\u51FA\u7B80\u77ED\u660E\u786E\u7684\u6279\u51C6\u8868\u8FF0\u540E\u5F15\u7528\u5176\u539F\u6587`,
|
|
8746
|
+
httpStatus: 0
|
|
8747
|
+
}
|
|
8748
|
+
});
|
|
8749
|
+
return;
|
|
8750
|
+
}
|
|
8751
|
+
const projectR = await resolveScopedProject(client, opts.project, "ws-default", { commandLabel: "siming issue add" });
|
|
8752
|
+
if (!projectR.success) {
|
|
8753
|
+
renderResult(opts.format ?? "fancy", projectR);
|
|
8754
|
+
return;
|
|
8550
8755
|
}
|
|
8756
|
+
const projectId = projectR.data.projectId;
|
|
8551
8757
|
const result = await handleCreateIssue(client, {
|
|
8552
8758
|
title,
|
|
8553
8759
|
...opts.description !== void 0 ? { description: opts.description } : {},
|
|
8554
|
-
...projectId !== void 0 ? { projectId } : {}
|
|
8760
|
+
...projectId !== void 0 ? { projectId } : {},
|
|
8761
|
+
approved: opts.approved
|
|
8555
8762
|
});
|
|
8556
8763
|
renderResult(opts.format ?? "fancy", result);
|
|
8557
8764
|
});
|
|
8558
|
-
withCommonOpts(issue.command("list"), "table").option("--status <s>", "filter by issue status (pending|partial|converted|cancelled)").option("--source <s>", "filter by source channel (mcp|cli|web)").option("--project <key
|
|
8765
|
+
withCommonOpts(issue.command("list"), "table").option("--status <s>", "filter by issue status (pending|partial|converted|cancelled|done)").option("--source <s>", "filter by source channel (mcp|cli|web)").option("--project <key|id>", "filter by projectId (key|id)").option("--task <taskId>", "filter by linked task").option("--q <keyword>", "search in title/description").option("--view <v>", "view: all|open (default all; open = \u6709\u6548\u672A\u8DDF\u8FDB\u5B8C)").option("--page <n>", "page number (default 1)", "1").option("--limit <n>", `page size (default ${PAGE_DEFAULT2}, max ${PAGE_MAX2})`).option("--all", `show all (limit ${PAGE_MAX2})`).description("List issues (with progress aggregation done/cancelled/total)").action(async (opts) => {
|
|
8559
8766
|
const client = createClient(opts.url);
|
|
8560
8767
|
const filters = {};
|
|
8561
8768
|
if (opts.status) filters.status = opts.status;
|
|
@@ -8570,13 +8777,14 @@ function createIssueCommand() {
|
|
|
8570
8777
|
}
|
|
8571
8778
|
filters.view = r.data;
|
|
8572
8779
|
}
|
|
8573
|
-
if (opts.project) {
|
|
8574
|
-
const
|
|
8575
|
-
if (!
|
|
8576
|
-
renderResult(opts.format ?? "table",
|
|
8780
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
8781
|
+
const pr = await resolveScopedProject(client, opts.project, "explicit-only");
|
|
8782
|
+
if (!pr.success) {
|
|
8783
|
+
renderResult(opts.format ?? "table", pr);
|
|
8577
8784
|
return;
|
|
8578
8785
|
}
|
|
8579
|
-
|
|
8786
|
+
const pid = pr.data.projectId;
|
|
8787
|
+
if (pid !== void 0) filters.projectId = pid;
|
|
8580
8788
|
}
|
|
8581
8789
|
if (opts.all) {
|
|
8582
8790
|
filters.limit = PAGE_MAX2;
|
|
@@ -8656,7 +8864,12 @@ function createIssueCommand() {
|
|
|
8656
8864
|
const result = await handleCancelIssue(client, issueId, opts.reason);
|
|
8657
8865
|
renderResult(opts.format ?? "fancy", result);
|
|
8658
8866
|
});
|
|
8659
|
-
withCommonOpts(issue.command("
|
|
8867
|
+
withCommonOpts(issue.command("done"), "fancy").argument("<issueId>", "issue id (I-prefixed)").option("--note <n>", "completion note (optional, \u2264500 chars \u2014 e.g. \u5728\u54EA\u4E2A\u4EFB\u52A1/\u54EA\u6B21\u6539\u52A8\u4E2D\u987A\u5E26\u89E3\u51B3)").description("Mark an issue as done directly (terminal state; keep taskLinks)").action(async (issueId, opts) => {
|
|
8868
|
+
const client = createClient(opts.url);
|
|
8869
|
+
const result = await handleDoneIssue(client, issueId, opts.note);
|
|
8870
|
+
renderResult(opts.format ?? "fancy", result);
|
|
8871
|
+
});
|
|
8872
|
+
withCommonOpts(issue.command("convert"), "fancy").requiredOption("--issue-ids <ids>", "comma-separated issue ids (or repeatable flag)", collectArgs, []).option("--declaration <mode>", "uniform declaration for all issues: all|partial (default all)").option("--declarations <map>", "per-issue declarations: id1:all,id2:partial (overrides --declaration)").requiredOption("--title <t>", "new task title").requiredOption("--template <code|name|id>", "DAG template code (preferred), name, or 24-hex id").requiredOption("--track <t>", "task track (backend|ui|mixed|research)").option("--type <t>", "task type (feature|bugfix|ui-tweak|research)").option("--skip <ids>", "node ids to prune (comma-separated, repeatable)", collectArgs, []).option("--project <key|id>", "projectId (key|id; issues and new task must belong to it)").description("Convert issues to a task (single group: N issues \u2192 1 task; split = multiple calls)").action(async (opts) => {
|
|
8660
8873
|
const client = createClient(opts.url);
|
|
8661
8874
|
const issueIds = [
|
|
8662
8875
|
...new Set((opts.issueIds ?? []).flatMap((s) => s.split(",")).map((s) => s.trim()).filter((s) => s.length > 0))
|
|
@@ -8687,13 +8900,13 @@ function createIssueCommand() {
|
|
|
8687
8900
|
declarations = Object.fromEntries(issueIds.map((id) => [id, "all"]));
|
|
8688
8901
|
}
|
|
8689
8902
|
let projectId;
|
|
8690
|
-
if (opts.project) {
|
|
8691
|
-
const
|
|
8692
|
-
if (!
|
|
8693
|
-
renderResult(opts.format ?? "fancy",
|
|
8903
|
+
if (opts.project !== void 0 && opts.project.trim().length > 0) {
|
|
8904
|
+
const pr = await resolveScopedProject(client, opts.project, "explicit-only");
|
|
8905
|
+
if (!pr.success) {
|
|
8906
|
+
renderResult(opts.format ?? "fancy", pr);
|
|
8694
8907
|
return;
|
|
8695
8908
|
}
|
|
8696
|
-
projectId =
|
|
8909
|
+
projectId = pr.data.projectId;
|
|
8697
8910
|
} else {
|
|
8698
8911
|
const first = await handleGetIssue(client, issueIds[0]);
|
|
8699
8912
|
if (!first.success) {
|