@siming-org/cli 0.3.0 → 0.4.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { Command as Command15 } from "commander";
2
+ import { Command as Command16 } from "commander";
3
3
  import { VERSION as VERSION5 } from "@siming-org/core";
4
4
 
5
5
  // src/output/fancy.ts
@@ -469,7 +469,7 @@ async function healthcheckCommand(opts) {
469
469
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
470
470
 
471
471
  // src/mcp/server.ts
472
- import { readFileSync as readFileSync6 } from "fs";
472
+ import { readFileSync as readFileSync7 } from "fs";
473
473
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
474
474
  import { VERSION as VERSION3, EnumRegistryUpdateSchema } from "@siming-org/core";
475
475
 
@@ -495,6 +495,9 @@ async function handlePause(client, taskId, reason) {
495
495
  async function handleResume(client, taskId, decision) {
496
496
  return client.postJson(`/api/tasks/${taskId}/resume`, decision ? { decision } : {});
497
497
  }
498
+ async function handleCancel(client, taskId, reason) {
499
+ return client.postJson(`/api/tasks/${taskId}/cancel`, reason !== void 0 ? { reason } : {});
500
+ }
498
501
  async function handleListTasks(client, filters) {
499
502
  const qs = new URLSearchParams();
500
503
  if (filters?.status) qs.set("status", filters.status);
@@ -509,8 +512,8 @@ async function handleListTasks(client, filters) {
509
512
  async function handleQueryState(client, taskId) {
510
513
  return client.getJson(`/api/tasks/${taskId}`);
511
514
  }
512
- async function handleGetContext(client, taskId) {
513
- return client.getJson(`/api/tasks/${taskId}/context`);
515
+ async function handleGetContext(client, taskId, view) {
516
+ return client.getJson(`/api/tasks/${taskId}/context${view !== void 0 ? `?view=${view}` : ""}`);
514
517
  }
515
518
  async function handleGetNodePrompt(client, taskId, nodeId) {
516
519
  return client.getJson(`/api/tasks/${taskId}/node/${nodeId}`);
@@ -570,7 +573,11 @@ function handleArchNoteAdd(client, taskId, text) {
570
573
  // src/client/handlers/dag.ts
571
574
  import { readFileSync as readFileSync4 } from "fs";
572
575
  import { parse as parseYaml } from "yaml";
573
- import { DagTemplateCreateSchema } from "@siming-org/core";
576
+ import {
577
+ DagTemplateCreateSchema,
578
+ ExportBundleSchema,
579
+ EXPORT_FORMAT_VERSION
580
+ } from "@siming-org/core";
574
581
  async function handleListTemplates(client, projectId) {
575
582
  return client.getJson(`/api/dag/templates${projectId ? `?projectId=${encodeURIComponent(projectId)}` : ""}`);
576
583
  }
@@ -595,7 +602,11 @@ async function importTemplateFromYaml(client, yamlText, opts) {
595
602
  try {
596
603
  raw = parseYaml(yamlText);
597
604
  } catch (e) {
598
- return fail({ message: `YAML \u89E3\u6790\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`, httpStatus: 0 });
605
+ return fail({
606
+ message: `YAML \u89E3\u6790\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`,
607
+ httpStatus: 0,
608
+ bizCode: "YAML_PARSE_FAILED"
609
+ });
599
610
  }
600
611
  const obj = raw ?? {};
601
612
  const projectId = opts.projectId ?? (typeof obj.projectId === "string" ? obj.projectId : void 0);
@@ -611,14 +622,56 @@ ${issues}`, httpStatus: 0 });
611
622
  }
612
623
  return client.postJson("/api/dag/templates", parsed.data);
613
624
  }
614
- async function handleImportTemplate(client, filePath, opts) {
615
- let yamlText;
625
+ async function importTemplateBundle(client, bundleText, opts) {
626
+ let raw;
616
627
  try {
617
- yamlText = readFileSync4(filePath, "utf-8");
628
+ raw = JSON.parse(bundleText);
618
629
  } catch (e) {
619
- return fail({ message: `\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25: ${filePath}\uFF08${e instanceof Error ? e.message : String(e)}\uFF09`, httpStatus: 0 });
630
+ return fail({ message: `bundle \u89E3\u6790\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`, httpStatus: 0 });
631
+ }
632
+ const parsed = ExportBundleSchema.safeParse(raw);
633
+ if (!parsed.success) {
634
+ const issues = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("\n");
635
+ const hasVersionField = typeof raw === "object" && raw !== null && "exportFormatVersion" in raw;
636
+ const versionMismatch = hasVersionField && parsed.error.issues.some((i) => i.path.includes("exportFormatVersion"));
637
+ return fail({
638
+ message: versionMismatch ? `bundle \u683C\u5F0F\u7248\u672C\u4E0D\u652F\u6301\uFF0C\u5F53\u524D\u652F\u6301 ${EXPORT_FORMAT_VERSION}\uFF0C\u8BF7\u5347\u7EA7 CLI \u7248\u672C
639
+ ${issues}` : `bundle \u6821\u9A8C\u5931\u8D25:
640
+ ${issues}`,
641
+ httpStatus: 0
642
+ });
620
643
  }
621
- return importTemplateFromYaml(client, yamlText, opts);
644
+ const bundle = parsed.data;
645
+ const plan = await client.postJson("/api/dag/templates/import/plan", {
646
+ targetProjectId: opts.targetProjectId,
647
+ bundle
648
+ });
649
+ if (!plan.success) return plan;
650
+ if (opts.planOnly === true) return { success: true, data: { plan: plan.data } };
651
+ const decisions = [];
652
+ if (opts.overwriteDeps === true) {
653
+ for (const dep of plan.data.dependencies) {
654
+ if (dep.status !== "conflict") continue;
655
+ if (dep.kind === "modelAlias") {
656
+ decisions.push({ kind: "modelAlias", name: dep.name, action: "overwrite" });
657
+ } else if (dep.scope !== void 0) {
658
+ decisions.push({ kind: dep.kind, name: dep.name, scope: dep.scope, action: "overwrite" });
659
+ } else {
660
+ return fail({
661
+ message: `server plan \u54CD\u5E94\u5F02\u5E38\uFF1A${dep.kind} "${dep.name}" \u7F3A scope \u5B57\u6BB5`,
662
+ httpStatus: 0,
663
+ hint: "skill/agent \u4F9D\u8D56\u5FC5\u987B\u643A\u5E26 scope\u2014\u2014\u91CD\u8BD5\u4ECD\u590D\u73B0\u5219\u68C0\u67E5 server \u7248\u672C"
664
+ });
665
+ }
666
+ }
667
+ }
668
+ const apply = await client.postJson("/api/dag/templates/import/apply", {
669
+ targetProjectId: opts.targetProjectId,
670
+ bundle,
671
+ decisions
672
+ });
673
+ if (!apply.success) return apply;
674
+ return { success: true, data: { plan: plan.data, apply: apply.data } };
622
675
  }
623
676
  async function handleGetInstance(client, taskId) {
624
677
  const result = await client.getJson(`/api/tasks/${encodeURIComponent(taskId)}`);
@@ -640,6 +693,7 @@ async function handleListSkills(client, query) {
640
693
  const qs = new URLSearchParams();
641
694
  if (q.projectId) qs.set("projectId", q.projectId);
642
695
  if (q.scope) qs.set("scope", q.scope);
696
+ if (q.includeDisabled !== void 0) qs.set("includeDisabled", String(q.includeDisabled));
643
697
  const qstr = qs.toString();
644
698
  return client.getJson(`/api/skills${qstr ? `?${qstr}` : ""}`);
645
699
  }
@@ -669,6 +723,7 @@ async function handleListAgents(client, query) {
669
723
  const qs = new URLSearchParams();
670
724
  if (q.projectId) qs.set("projectId", q.projectId);
671
725
  if (q.scope) qs.set("scope", q.scope);
726
+ if (q.includeDisabled !== void 0) qs.set("includeDisabled", String(q.includeDisabled));
672
727
  const qstr = qs.toString();
673
728
  return client.getJson(`/api/agents${qstr ? `?${qstr}` : ""}`);
674
729
  }
@@ -861,12 +916,13 @@ import {
861
916
  ARTIFACT_TYPES,
862
917
  SkillScopeSchema,
863
918
  AgentScopeSchema,
919
+ AgentFunctionSchema,
864
920
  ProjectStatusSchema,
865
921
  EnumRegistryCategorySchema
866
922
  } from "@siming-org/core";
867
923
  var taskArgs = {
868
924
  action: z3.enum([
869
- // 任务生命周期(8 机械映射 + query 例外:task list/show 合一)
925
+ // 任务生命周期(9 机械映射 + query 例外:task list/show 合一)
870
926
  "create",
871
927
  "query",
872
928
  "context",
@@ -875,6 +931,7 @@ var taskArgs = {
875
931
  "approve",
876
932
  "pause",
877
933
  "resume",
934
+ "cancel",
878
935
  "history",
879
936
  // 实例(例外:映射自 dag instance)
880
937
  "instance",
@@ -905,8 +962,9 @@ var taskArgs = {
905
962
  status: z3.string().optional(),
906
963
  page: z3.number().int().min(1).optional(),
907
964
  limit: z3.number().int().min(1).max(500).optional(),
908
- // node
909
- view: z3.enum(["prompt", "skills"]).optional(),
965
+ // node / context(T202608280007 D5:view 四值并集——node 只认 prompt|skills,
966
+ // context 只认 basic|full,per-action 校验归 mcp/server.ts;非法组合报失败三要素)
967
+ view: z3.enum(["prompt", "skills", "basic", "full"]).optional(),
910
968
  nodeId: z3.string().optional(),
911
969
  // advance / record-set(note 写 history;summary 写 nodeRecords,两位独立)
912
970
  note: z3.string().optional(),
@@ -949,6 +1007,10 @@ var syncArgs = {
949
1007
  action: z3.enum(["run", "status"]),
950
1008
  targetType: z3.enum(["skills", "agents", "all"]).optional()
951
1009
  };
1010
+ var referenceDocSchema = z3.object({
1011
+ path: z3.string(),
1012
+ content: z3.string()
1013
+ });
952
1014
  var skillArgs = {
953
1015
  action: z3.enum(["list", "show", "create", "update", "copy", "delete"]),
954
1016
  name: z3.string().optional(),
@@ -958,6 +1020,9 @@ var skillArgs = {
958
1020
  content: z3.string().optional(),
959
1021
  description: z3.string().optional(),
960
1022
  version: z3.string().optional(),
1023
+ /** create=初始引用集合;update=整笔替换(缺省 = 不修改;clearRefs=true = 清空) */
1024
+ references: z3.array(referenceDocSchema).optional(),
1025
+ clearRefs: z3.boolean().optional(),
961
1026
  newName: z3.string().optional(),
962
1027
  newScope: SkillScopeSchema.optional(),
963
1028
  targetProjectId: z3.string().optional()
@@ -970,9 +1035,14 @@ var agentArgs = {
970
1035
  description: z3.string().optional(),
971
1036
  systemPrompt: z3.string().optional(),
972
1037
  model: z3.string().optional(),
1038
+ /** T202608260002:功能类型 reviewer|executor(缺省 executor)——仅 reviewer 在 install 落盘注入信息边界 */
1039
+ "function": AgentFunctionSchema.optional(),
973
1040
  tools: z3.array(z3.string()).optional(),
974
1041
  permissions: z3.array(z3.string()).optional(),
975
1042
  boundSkills: z3.array(z3.string()).optional(),
1043
+ /** create=初始引用集合;update=整笔替换(缺省 = 不修改;clearRefs=true = 清空) */
1044
+ references: z3.array(referenceDocSchema).optional(),
1045
+ clearRefs: z3.boolean().optional(),
976
1046
  newName: z3.string().optional(),
977
1047
  newScope: AgentScopeSchema.optional(),
978
1048
  targetProjectId: z3.string().optional()
@@ -1020,13 +1090,27 @@ var initArgs = {
1020
1090
  var doctorArgs = {};
1021
1091
 
1022
1092
  // src/client/handlers/export.ts
1023
- function bumpPatch(version) {
1024
- const m = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
1025
- if (!m) return version;
1026
- return `${m[1]}.${m[2]}.${Number(m[3]) + 1}`;
1093
+ import { AGENT_MAIN_DOC, REFERENCE_LIMITS, SKILL_MAIN_DOC, bumpPatchOrPassthrough, createReferencesSchema, sumReferenceContentChars } from "@siming-org/core";
1094
+ function refsSuffix(base, references) {
1095
+ return references !== void 0 ? `${base}\uFF0Crefs=${String(references.length)}` : base;
1027
1096
  }
1028
1097
  var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
1029
1098
  var DEFAULT_VERSION = "1.0.0";
1099
+ function parseEntryReferences(entity, raw) {
1100
+ if (!("references" in raw)) return {};
1101
+ const rawRefs = raw.references;
1102
+ if (!Array.isArray(rawRefs)) {
1103
+ return { error: "references \u5FC5\u987B\u662F\u6570\u7EC4\uFF08\u952E\u7F3A\u5931 = \u4E0D\u4FEE\u6539\u670D\u52A1\u7AEF\u73B0\u503C\uFF1B\u663E\u5F0F [] = \u6E05\u7A7A\u5F15\u7528\u6587\u6863\uFF09" };
1104
+ }
1105
+ const parsed = createReferencesSchema(entity === "skill" ? SKILL_MAIN_DOC : AGENT_MAIN_DOC).safeParse(rawRefs);
1106
+ if (!parsed.success) {
1107
+ const first = parsed.error.issues[0];
1108
+ return {
1109
+ error: `references \u975E\u6CD5\uFF1A${first?.message ?? "\u6821\u9A8C\u5931\u8D25"}${parsed.error.issues.length > 1 ? `\uFF08\u5171 ${String(parsed.error.issues.length)} \u5904\u95EE\u9898\uFF09` : ""}`
1110
+ };
1111
+ }
1112
+ return { refs: parsed.data };
1113
+ }
1030
1114
  function migrateLegacyPausePoints(edges, pausePoints) {
1031
1115
  if (pausePoints.length === 0) return edges;
1032
1116
  const result = edges.map((e) => isObject(e) ? { ...e } : e);
@@ -1077,6 +1161,16 @@ function normalizeExportEntries(raw) {
1077
1161
  errors.push({ name, type: "skill", action: "error", reason: "scope=project \u65F6\u5FC5\u586B projectKey", fieldPath: `skills[${i}].projectKey`, expected: "string (\u9879\u76EE key\uFF0C\u89C1 siming project list)" });
1078
1162
  continue;
1079
1163
  }
1164
+ const skillRefs = parseEntryReferences("skill", item);
1165
+ if (skillRefs.error !== void 0) {
1166
+ errors.push({ name, type: "skill", action: "error", reason: skillRefs.error, fieldPath: `skills[${i}].references`, expected: `array of {path, content}\uFF08\u76F8\u5BF9\u8DEF\u5F84\uFF1B\u7981\u7EDD\u5BF9\u8DEF\u5F84/../\u53CD\u659C\u6760/\u4E3B\u6587\u6863\u540D ${SKILL_MAIN_DOC} \u51B2\u7A81\uFF09` });
1167
+ continue;
1168
+ }
1169
+ const totalChars = item.content.length + sumReferenceContentChars(skillRefs.refs);
1170
+ if (totalChars > REFERENCE_LIMITS.maxTotalChars) {
1171
+ errors.push({ name, type: "skill", action: "error", reason: `\u4E3B\u6587\u6863\u4E0E\u5F15\u7528\u6587\u6863\u5185\u5BB9\u603B\u91CF ${String(totalChars)} \u5B57\u7B26\u8D85\u51FA\u805A\u5408\u4E0A\u9650 ${String(REFERENCE_LIMITS.maxTotalChars)}`, fieldPath: `skills[${i}].references`, expected: `\u603B\u91CF \u2264 ${String(REFERENCE_LIMITS.maxTotalChars)} \u5B57\u7B26` });
1172
+ continue;
1173
+ }
1080
1174
  skills.push({
1081
1175
  name,
1082
1176
  description: typeof item.description === "string" ? item.description : "",
@@ -1084,6 +1178,7 @@ function normalizeExportEntries(raw) {
1084
1178
  category: item.category === "domain" || item.category === "tooling" ? item.category : "process",
1085
1179
  version: typeof item.version === "string" && item.version ? item.version : DEFAULT_VERSION,
1086
1180
  scope,
1181
+ ...skillRefs.refs !== void 0 ? { references: skillRefs.refs } : {},
1087
1182
  ...scope === "project" && typeof item.projectKey === "string" ? { projectKey: item.projectKey } : {},
1088
1183
  ...item.skipExisting === true ? { skipExisting: true } : {}
1089
1184
  });
@@ -1112,6 +1207,16 @@ function normalizeExportEntries(raw) {
1112
1207
  continue;
1113
1208
  }
1114
1209
  const strArr = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
1210
+ const agentRefs = parseEntryReferences("agent", item);
1211
+ if (agentRefs.error !== void 0) {
1212
+ errors.push({ name, type: "agent", action: "error", reason: agentRefs.error, fieldPath: `agents[${i}].references`, expected: `array of {path, content}\uFF08\u76F8\u5BF9\u8DEF\u5F84\uFF1B\u7981\u7EDD\u5BF9\u8DEF\u5F84/../\u53CD\u659C\u6760/\u4E3B\u6587\u6863\u540D ${AGENT_MAIN_DOC} \u51B2\u7A81\uFF09` });
1213
+ continue;
1214
+ }
1215
+ const totalAgentChars = item.systemPrompt.length + sumReferenceContentChars(agentRefs.refs);
1216
+ if (totalAgentChars > REFERENCE_LIMITS.maxTotalChars) {
1217
+ errors.push({ name, type: "agent", action: "error", reason: `\u4E3B\u6587\u6863\u4E0E\u5F15\u7528\u6587\u6863\u5185\u5BB9\u603B\u91CF ${String(totalAgentChars)} \u5B57\u7B26\u8D85\u51FA\u805A\u5408\u4E0A\u9650 ${String(REFERENCE_LIMITS.maxTotalChars)}`, fieldPath: `agents[${i}].references`, expected: `\u603B\u91CF \u2264 ${String(REFERENCE_LIMITS.maxTotalChars)} \u5B57\u7B26` });
1218
+ continue;
1219
+ }
1115
1220
  agents.push({
1116
1221
  name,
1117
1222
  description: typeof item.description === "string" ? item.description : "",
@@ -1122,6 +1227,7 @@ function normalizeExportEntries(raw) {
1122
1227
  permissions: strArr(item.permissions),
1123
1228
  version: typeof item.version === "string" && item.version ? item.version : DEFAULT_VERSION,
1124
1229
  scope,
1230
+ ...agentRefs.refs !== void 0 ? { references: agentRefs.refs } : {},
1125
1231
  ...scope === "project" && typeof item.projectKey === "string" ? { projectKey: item.projectKey } : {},
1126
1232
  ...item.skipExisting === true ? { skipExisting: true } : {}
1127
1233
  });
@@ -1203,7 +1309,7 @@ async function buildExportPlan(client, set, opts) {
1203
1309
  items.push({ name: s.name, type: "skill", action: "error", reason: `projectKey '${s.projectKey}' \u4E0D\u5B58\u5728`, hint: "check `siming project list` \u83B7\u53D6\u6B63\u786E\u7684 key", fieldPath: "projectKey" });
1204
1310
  continue;
1205
1311
  }
1206
- const existing = await client.getJson(`/api/skills/${encodeURIComponent(s.name)}`);
1312
+ const existing = await client.getJson(`/api/skills/${encodeURIComponent(s.name)}?includeDisabled=true`);
1207
1313
  if (!existing.success && existing.error.httpStatus !== 404) {
1208
1314
  items.push({ name: s.name, type: "skill", action: "error", reason: `\u67E5\u8BE2 server \u5931\u8D25: ${existing.error.message}`, ...existing.error.hint ? { hint: existing.error.hint } : {}, fieldPath: "server" });
1209
1315
  continue;
@@ -1214,7 +1320,7 @@ async function buildExportPlan(client, set, opts) {
1214
1320
  name: s.name,
1215
1321
  type: "skill",
1216
1322
  action: "created",
1217
- reason: "server \u65E0\u540C\u540D\u8D44\u4EA7",
1323
+ reason: refsSuffix("server \u65E0\u540C\u540D\u8D44\u4EA7", s.references),
1218
1324
  payload: {
1219
1325
  name: s.name,
1220
1326
  description: s.description,
@@ -1222,11 +1328,23 @@ async function buildExportPlan(client, set, opts) {
1222
1328
  category: s.category,
1223
1329
  version: s.version,
1224
1330
  scope: s.scope,
1331
+ ...s.references !== void 0 ? { references: s.references } : {},
1225
1332
  ...s.scope === "project" ? { projectId } : {}
1226
1333
  }
1227
1334
  });
1228
1335
  continue;
1229
1336
  }
1337
+ if (ex.enabled === false) {
1338
+ items.push({
1339
+ name: s.name,
1340
+ type: "skill",
1341
+ action: "error",
1342
+ reason: "server \u5B58\u5728\u540C\u540D\u5DF2\u505C\u7528\u8D44\u4EA7\uFF08\u5217\u8868\u89C6\u56FE\u4E0D\u53EF\u89C1\uFF09",
1343
+ hint: "\u5728 Web \u7BA1\u7406\u53F0\u91CD\u65B0\u542F\u7528\u8BE5\u8D44\u4EA7\u540E\u91CD\u8BD5 export\uFF0C\u6216\u4FEE\u6539\u672C\u5730\u6761\u76EE\u540D",
1344
+ fieldPath: "server"
1345
+ });
1346
+ continue;
1347
+ }
1230
1348
  if (ex.scope !== s.scope) {
1231
1349
  items.push({
1232
1350
  name: s.name,
@@ -1259,27 +1377,29 @@ async function buildExportPlan(client, set, opts) {
1259
1377
  name: s.name,
1260
1378
  type: "skill",
1261
1379
  action: "updated",
1262
- reason: `\u6761\u76EE\u7248\u672C ${s.version} \u2260 server ${serverVer ?? "\u65E0"}\uFF0C\u6309\u6761\u76EE\u7248\u672C\u66F4\u65B0`,
1380
+ reason: refsSuffix(`\u6761\u76EE\u7248\u672C ${s.version} \u2260 server ${serverVer ?? "\u65E0"}\uFF0C\u6309\u6761\u76EE\u7248\u672C\u66F4\u65B0`, s.references),
1263
1381
  payload: {
1264
1382
  description: s.description,
1265
1383
  content: s.content,
1266
1384
  category: s.category,
1267
1385
  version: s.version,
1386
+ ...s.references !== void 0 ? { references: s.references } : {},
1268
1387
  ...s.scope === "project" ? { projectId } : {}
1269
1388
  }
1270
1389
  });
1271
1390
  } else {
1272
- const next = bumpPatch(serverVer ?? s.version);
1391
+ const next = bumpPatchOrPassthrough(serverVer ?? s.version);
1273
1392
  items.push({
1274
1393
  name: s.name,
1275
1394
  type: "skill",
1276
1395
  action: "updated",
1277
- reason: `\u7248\u672C\u76F8\u540C\uFF08${serverVer}\uFF09\uFF0C\u81EA\u52A8\u9012\u589E\u5230 ${next}`,
1396
+ reason: refsSuffix(`\u7248\u672C\u76F8\u540C\uFF08${serverVer}\uFF09\uFF0C\u81EA\u52A8\u9012\u589E\u5230 ${next}`, s.references),
1278
1397
  payload: {
1279
1398
  description: s.description,
1280
1399
  content: s.content,
1281
1400
  category: s.category,
1282
1401
  version: next,
1402
+ ...s.references !== void 0 ? { references: s.references } : {},
1283
1403
  ...s.scope === "project" ? { projectId } : {}
1284
1404
  }
1285
1405
  });
@@ -1305,7 +1425,7 @@ async function buildExportPlan(client, set, opts) {
1305
1425
  });
1306
1426
  continue;
1307
1427
  }
1308
- const existing = await client.getJson(`/api/agents/${encodeURIComponent(a.name)}`);
1428
+ const existing = await client.getJson(`/api/agents/${encodeURIComponent(a.name)}?includeDisabled=true`);
1309
1429
  if (!existing.success && existing.error.httpStatus !== 404) {
1310
1430
  items.push({ name: a.name, type: "agent", action: "error", reason: `\u67E5\u8BE2 server \u5931\u8D25: ${existing.error.message}`, ...existing.error.hint ? { hint: existing.error.hint } : {}, fieldPath: "server" });
1311
1431
  continue;
@@ -1316,7 +1436,7 @@ async function buildExportPlan(client, set, opts) {
1316
1436
  name: a.name,
1317
1437
  type: "agent",
1318
1438
  action: "created",
1319
- reason: "server \u65E0\u540C\u540D\u8D44\u4EA7",
1439
+ reason: refsSuffix("server \u65E0\u540C\u540D\u8D44\u4EA7", a.references),
1320
1440
  payload: {
1321
1441
  name: a.name,
1322
1442
  description: a.description,
@@ -1327,11 +1447,23 @@ async function buildExportPlan(client, set, opts) {
1327
1447
  permissions: a.permissions,
1328
1448
  version: a.version,
1329
1449
  scope: a.scope,
1450
+ ...a.references !== void 0 ? { references: a.references } : {},
1330
1451
  ...a.scope === "project" ? { projectId } : {}
1331
1452
  }
1332
1453
  });
1333
1454
  continue;
1334
1455
  }
1456
+ if (ex.enabled === false) {
1457
+ items.push({
1458
+ name: a.name,
1459
+ type: "agent",
1460
+ action: "error",
1461
+ reason: "server \u5B58\u5728\u540C\u540D\u5DF2\u505C\u7528\u8D44\u4EA7\uFF08\u5217\u8868\u89C6\u56FE\u4E0D\u53EF\u89C1\uFF09",
1462
+ hint: "\u5728 Web \u7BA1\u7406\u53F0\u91CD\u65B0\u542F\u7528\u8BE5\u8D44\u4EA7\u540E\u91CD\u8BD5 export\uFF0C\u6216\u4FEE\u6539\u672C\u5730\u6761\u76EE\u540D",
1463
+ fieldPath: "server"
1464
+ });
1465
+ continue;
1466
+ }
1335
1467
  if (ex.scope !== a.scope) {
1336
1468
  items.push({
1337
1469
  name: a.name,
@@ -1366,6 +1498,7 @@ async function buildExportPlan(client, set, opts) {
1366
1498
  boundSkills: a.boundSkills,
1367
1499
  tools: a.tools,
1368
1500
  permissions: a.permissions,
1501
+ ...a.references !== void 0 ? { references: a.references } : {},
1369
1502
  ...a.scope === "project" ? { projectId } : {}
1370
1503
  };
1371
1504
  if (a.version !== serverVer) {
@@ -1373,16 +1506,16 @@ async function buildExportPlan(client, set, opts) {
1373
1506
  name: a.name,
1374
1507
  type: "agent",
1375
1508
  action: "updated",
1376
- reason: `\u6761\u76EE\u7248\u672C ${a.version} \u2260 server ${serverVer ?? "\u65E0"}\uFF0C\u6309\u6761\u76EE\u7248\u672C\u66F4\u65B0`,
1509
+ reason: refsSuffix(`\u6761\u76EE\u7248\u672C ${a.version} \u2260 server ${serverVer ?? "\u65E0"}\uFF0C\u6309\u6761\u76EE\u7248\u672C\u66F4\u65B0`, a.references),
1377
1510
  payload: { ...patch, version: a.version }
1378
1511
  });
1379
1512
  } else {
1380
- const next = bumpPatch(serverVer ?? a.version);
1513
+ const next = bumpPatchOrPassthrough(serverVer ?? a.version);
1381
1514
  items.push({
1382
1515
  name: a.name,
1383
1516
  type: "agent",
1384
1517
  action: "updated",
1385
- reason: `\u7248\u672C\u76F8\u540C\uFF08${serverVer}\uFF09\uFF0C\u81EA\u52A8\u9012\u589E\u5230 ${next}`,
1518
+ reason: refsSuffix(`\u7248\u672C\u76F8\u540C\uFF08${serverVer}\uFF09\uFF0C\u81EA\u52A8\u9012\u589E\u5230 ${next}`, a.references),
1386
1519
  payload: { ...patch, version: next }
1387
1520
  });
1388
1521
  }
@@ -1396,7 +1529,8 @@ async function buildExportPlan(client, set, opts) {
1396
1529
  continue;
1397
1530
  }
1398
1531
  const listR = await client.getJson(
1399
- `/api/dag/templates?projectId=${encodeURIComponent(projectId)}&name=${encodeURIComponent(d.name)}`
1532
+ // T202608290001:includeDisabled=true——停用模板与不存在区分(否则缺省过滤 → 误判 created → apply 撞 {projectId,name} 唯一索引 409)
1533
+ `/api/dag/templates?projectId=${encodeURIComponent(projectId)}&name=${encodeURIComponent(d.name)}&includeDisabled=true`
1400
1534
  );
1401
1535
  if (!listR.success) {
1402
1536
  items.push({ name: d.name, type: "dag", action: "error", reason: `\u67E5\u8BE2 server \u5931\u8D25: ${listR.error.message}`, ...listR.error.hint ? { hint: listR.error.hint } : {}, fieldPath: "server" });
@@ -1416,6 +1550,17 @@ async function buildExportPlan(client, set, opts) {
1416
1550
  items.push({ name: d.name, type: "dag", action: "created", reason: `\u9879\u76EE ${d.projectKey} \u5185\u65E0\u540C\u540D\u6A21\u677F`, payload: createPayload });
1417
1551
  continue;
1418
1552
  }
1553
+ if (ex.enabled === false) {
1554
+ items.push({
1555
+ name: d.name,
1556
+ type: "dag",
1557
+ action: "error",
1558
+ reason: "server \u5B58\u5728\u540C\u540D\u5DF2\u505C\u7528\u6A21\u677F\uFF08\u5217\u8868\u89C6\u56FE\u4E0D\u53EF\u89C1\uFF09",
1559
+ hint: "\u5728 Web \u7BA1\u7406\u53F0\u91CD\u65B0\u542F\u7528\u8BE5\u6A21\u677F\u540E\u91CD\u8BD5 export\uFF0C\u6216\u4FEE\u6539\u672C\u5730\u6761\u76EE\u540D",
1560
+ fieldPath: "server"
1561
+ });
1562
+ continue;
1563
+ }
1419
1564
  if (ex.projectId !== projectId) {
1420
1565
  items.push({ name: d.name, type: "dag", action: "error", reason: `\u5F52\u5C5E\u9879\u76EE\u4E0D\u4E00\u81F4\uFF1Aserver=${byId.get(ex.projectId) ?? ex.projectId} vs \u6761\u76EE=${d.projectKey}\uFF08\u5F52\u5C5E\u4E0D\u53EF\u53D8\uFF09`, hint: "\u8C03\u6574\u6761\u76EE projectKey \u6216\u5148\u5220\u9664\u518D\u5BFC\u5165", fieldPath: "projectKey" });
1421
1566
  continue;
@@ -1441,7 +1586,7 @@ async function buildExportPlan(client, set, opts) {
1441
1586
  targetId: ex.id
1442
1587
  });
1443
1588
  } else {
1444
- const next = bumpPatch(serverVer ?? d.version);
1589
+ const next = bumpPatchOrPassthrough(serverVer ?? d.version);
1445
1590
  items.push({
1446
1591
  name: d.name,
1447
1592
  type: "dag",
@@ -1528,10 +1673,10 @@ async function applyExportPlan(client, plan, opts) {
1528
1673
 
1529
1674
  // src/commands/install/command.ts
1530
1675
  import { Command as Command2 } from "commander";
1531
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
1676
+ import { existsSync as existsSync5 } from "fs";
1532
1677
  import { createInterface } from "readline/promises";
1533
1678
  import { dirname as dirname3, join as join5 } from "path";
1534
- import { VERSION as VERSION2 } from "@siming-org/core";
1679
+ import { AGENT_MAIN_DOC as AGENT_MAIN_DOC3, SKILL_MAIN_DOC as SKILL_MAIN_DOC3, VERSION as VERSION2 } from "@siming-org/core";
1535
1680
 
1536
1681
  // src/output/json.ts
1537
1682
  function renderJson(value) {
@@ -1639,8 +1784,10 @@ function renderResult(format, result, opts) {
1639
1784
  }
1640
1785
 
1641
1786
  // src/commands/opts.ts
1787
+ import { readFileSync as readFileSync5 } from "fs";
1642
1788
  import "commander";
1643
1789
  import { z as z4 } from "zod";
1790
+ import { canonicalizeReferencePath, createReferencesSchema as createReferencesSchema2 } from "@siming-org/core";
1644
1791
  function withCommonOpts(cmd, defaultFormat) {
1645
1792
  return cmd.option("--url <url>", "server base URL").option("--format <fmt>", "output format: fancy|table|json", defaultFormat);
1646
1793
  }
@@ -1659,13 +1806,63 @@ function parseEnum(value, schema, optName) {
1659
1806
  return ok2(r.data);
1660
1807
  }
1661
1808
  var SkillCategorySchema = z4.string().min(1);
1809
+ function parseRefFlags(refs, mainDocName) {
1810
+ const docs = [];
1811
+ const seen = /* @__PURE__ */ new Set();
1812
+ const singlePathSchema = createReferencesSchema2(mainDocName);
1813
+ for (const [index, spec] of refs.entries()) {
1814
+ const at = spec.indexOf("@");
1815
+ if (at <= 0 || at === spec.length - 1) {
1816
+ return fail({
1817
+ message: `--ref \u7B2C ${String(index + 1)} \u9879\u683C\u5F0F\u975E\u6CD5\uFF1A"${spec}"`,
1818
+ httpStatus: 0,
1819
+ hint: "\u683C\u5F0F\uFF1A<\u5F15\u7528\u76F8\u5BF9\u8DEF\u5F84>@<\u672C\u5730\u6587\u4EF6\u8DEF\u5F84>\uFF0C\u5982 references/guide.md@./docs/guide.md"
1820
+ });
1821
+ }
1822
+ const relPath = spec.slice(0, at);
1823
+ const localPath = spec.slice(at + 1);
1824
+ const pathCheck = singlePathSchema.safeParse([{ path: relPath, content: "" }]);
1825
+ if (!pathCheck.success) {
1826
+ return fail({
1827
+ message: `--ref \u76F8\u5BF9\u8DEF\u5F84\u975E\u6CD5\uFF1A${pathCheck.error.issues[0]?.message ?? relPath}`,
1828
+ httpStatus: 0,
1829
+ hint: "\u5F15\u7528\u8DEF\u5F84\u5FC5\u987B\u662F\u76F8\u5BF9\u8D44\u4EA7\u6839\u7684\u6B63\u659C\u6760\u76F8\u5BF9\u8DEF\u5F84\uFF08\u7981\u7EDD\u5BF9\u8DEF\u5F84 / .. \u56DE\u6EAF / \u53CD\u659C\u6760 / \u7A7A\u6BB5\uFF09"
1830
+ });
1831
+ }
1832
+ if (seen.has(canonicalizeReferencePath(relPath))) {
1833
+ return fail({
1834
+ message: `--ref \u76F8\u5BF9\u8DEF\u5F84\u91CD\u590D\uFF1A"${relPath}"`,
1835
+ httpStatus: 0,
1836
+ hint: "\u540C\u4E00\u5F15\u7528\u8DEF\u5F84\u53EA\u80FD\u51FA\u73B0\u4E00\u6B21\uFF08\u5927\u5C0F\u5199/./ \u524D\u7F00\u5DEE\u5F02\u89C6\u4E3A\u76F8\u540C\u8DEF\u5F84\uFF09\uFF1B\u4E0D\u540C\u672C\u5730\u6587\u4EF6\u8BF7\u4F7F\u7528\u4E0D\u540C\u5F15\u7528\u8DEF\u5F84"
1837
+ });
1838
+ }
1839
+ seen.add(canonicalizeReferencePath(relPath));
1840
+ let content;
1841
+ try {
1842
+ content = readFileSync5(localPath, "utf-8");
1843
+ } catch (e) {
1844
+ return fail({
1845
+ message: `--ref \u672C\u5730\u6587\u4EF6\u4E0D\u53EF\u8BFB\uFF1A"${localPath}"`,
1846
+ httpStatus: 0,
1847
+ hint: `\u786E\u8BA4\u6587\u4EF6\u5B58\u5728\u4E14\u53EF\u8BFB\uFF08${e instanceof Error ? e.message : String(e)}\uFF09`
1848
+ });
1849
+ }
1850
+ docs.push({ path: relPath, content });
1851
+ }
1852
+ return ok2(docs);
1853
+ }
1662
1854
 
1663
1855
  // src/commands/install/writer.ts
1664
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
1856
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
1665
1857
  import { dirname as dirname2, join as join4 } from "path";
1666
1858
  import { homedir as homedir3 } from "os";
1667
1859
  import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
1668
- import { VERSION } from "@siming-org/core";
1860
+ import {
1861
+ AGENT_MAIN_DOC as AGENT_MAIN_DOC2,
1862
+ SKILL_MAIN_DOC as SKILL_MAIN_DOC2,
1863
+ VERSION,
1864
+ createReferencesSchema as createReferencesSchema3
1865
+ } from "@siming-org/core";
1669
1866
  function agentsHomeDir() {
1670
1867
  const env = process.env.SIMING_AGENTS_HOME;
1671
1868
  return env && env.length > 0 ? env : join4(homedir3(), ".agents");
@@ -1688,6 +1885,24 @@ function isSafeAssetName(name) {
1688
1885
  if (name.includes("/") || name.includes("\\")) return false;
1689
1886
  return true;
1690
1887
  }
1888
+ var REFERENCE_SCHEMAS = {
1889
+ [SKILL_MAIN_DOC2]: createReferencesSchema3(SKILL_MAIN_DOC2),
1890
+ [AGENT_MAIN_DOC2]: createReferencesSchema3(AGENT_MAIN_DOC2)
1891
+ };
1892
+ function validateReferencesLocally(mainDocName, references) {
1893
+ if (references === void 0) return null;
1894
+ const parsed = REFERENCE_SCHEMAS[mainDocName].safeParse(references);
1895
+ if (parsed.success) return null;
1896
+ return parsed.error.issues[0]?.message ?? "references \u6821\u9A8C\u5931\u8D25";
1897
+ }
1898
+ function writeAssetDirectory(assetDir, files) {
1899
+ rmSync2(assetDir, { recursive: true, force: true });
1900
+ for (const file of files) {
1901
+ const target = join4(assetDir, ...file.relPath.split("/"));
1902
+ mkdirSync3(dirname2(target), { recursive: true });
1903
+ writeFileSync3(target, file.content, "utf-8");
1904
+ }
1905
+ }
1691
1906
  function skillToMarkdown(skill) {
1692
1907
  const fm = stringifyYaml(
1693
1908
  { name: skill.name, description: skill.description, "siming-version": skill.version },
@@ -1710,7 +1925,7 @@ function permissionsToMatrix(permissions) {
1710
1925
  }
1711
1926
  return matrix;
1712
1927
  }
1713
- var AGENT_INFO_BOUNDARY = "\u4EFB\u52A1\u4F9D\u636E\u9650\u4E8E\u9879\u76EE\u4EE3\u7801\u3001\u5F00\u53D1\u6D41\u7A0B\u9636\u6BB5\u7684\u6267\u884C\u62A5\u544A/\u8BBE\u8BA1\u6587\u6863\u53CA\u59D4\u6D3E\u4EFB\u52A1\u63D0\u4F9B\u7684\u6750\u6599\uFF1B\u7981\u6B62\u81EA\u884C\u8BBF\u95EE\u65E5\u5FD7\u3001\u4E34\u65F6\u6587\u4EF6\u7B49\u8FC7\u7A0B\u4EA7\u7269\uFF0C\u59D4\u6D3E\u4EFB\u52A1\u660E\u786E\u8981\u6C42\u65F6\u9664\u5916\u3002";
1928
+ var AGENT_INFO_BOUNDARY = "\u4EFB\u52A1\u4F9D\u636E\u9650\u4E8E\u9879\u76EE\u4EE3\u7801\u3001\u8BBE\u8BA1\u6587\u6863/\u6267\u884C\u62A5\u544A\u53CA\u4EFB\u52A1\u4E0A\u4E0B\u6587\uFF08\u542B\u4EFB\u52A1\u4FE1\u606F\u3001\u63D0\u793A\u8BCD\u3001\u59D4\u6D3E\u6750\u6599\uFF09\uFF1B\u7981\u6B62\u81EA\u884C\u8BFB\u53D6\u65E5\u5FD7\u3001\u4E34\u65F6\u6587\u4EF6\u7B49\u8FC7\u7A0B\u4EA7\u7269\uFF0C\u7981\u6B62\u81EA\u884C\u6267\u884C\u6D4B\u8BD5\u3001\u547D\u4EE4\u6216\u5176\u4ED6\u64CD\u4F5C\uFF0C\u59D4\u6D3E\u4EFB\u52A1\u660E\u786E\u8981\u6C42\u65F6\u9664\u5916\u3002";
1714
1929
  function agentToMarkdown(agent, realModel) {
1715
1930
  const fm = {
1716
1931
  description: agent.description,
@@ -1724,7 +1939,8 @@ function agentToMarkdown(agent, realModel) {
1724
1939
  if (Object.keys(perms).length > 0) fm.permission = perms;
1725
1940
  const identity = "\u4F60\u662Fsubagent\uFF0C\u6B63\u5728\u63A5\u53D7\u4E3B\u4F1A\u8BDD\u7684\u59D4\u6D3E\u4EFB\u52A1\u3002";
1726
1941
  const skillLine = agent.boundSkills.length > 0 ? `\u8FD9\u4E2A\u4EFB\u52A1\u5FC5\u987B\u5148\u52A0\u8F7DSKILL\uFF1A${JSON.stringify(agent.boundSkills)} \u540E\u518D\u6267\u884C\u3002` : "";
1727
- const preamble = `${identity}${skillLine}${AGENT_INFO_BOUNDARY}`;
1942
+ const boundary = agent["function"] === "reviewer" ? AGENT_INFO_BOUNDARY : "";
1943
+ const preamble = `${identity}${skillLine}${boundary}`;
1728
1944
  return `---
1729
1945
  ${stringifyYaml(fm, { lineWidth: 0 })}---
1730
1946
 
@@ -1740,7 +1956,7 @@ function readSimingVersion(path) {
1740
1956
  if (!existsSync4(path)) return null;
1741
1957
  let text;
1742
1958
  try {
1743
- text = readFileSync5(path, "utf-8");
1959
+ text = readFileSync6(path, "utf-8");
1744
1960
  } catch {
1745
1961
  return null;
1746
1962
  }
@@ -1765,7 +1981,7 @@ function readMcpConfig(path) {
1765
1981
  if (!existsSync4(path)) return { state: "absent" };
1766
1982
  let text;
1767
1983
  try {
1768
- text = readFileSync5(path, "utf-8");
1984
+ text = readFileSync6(path, "utf-8");
1769
1985
  } catch (e) {
1770
1986
  return { state: "corrupt", error: `\u8BFB\u53D6\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}` };
1771
1987
  }
@@ -1877,7 +2093,7 @@ function createInstallCommand() {
1877
2093
  (i) => (opts.only ?? []).length === 0 || (opts.only ?? []).includes(i.name)
1878
2094
  );
1879
2095
  const actionable = selectedItems.filter(
1880
- (i) => opts.force || i.action === "install" || i.action === "update"
2096
+ (i) => !i.disabled && (opts.force || i.action === "install" || i.action === "update")
1881
2097
  );
1882
2098
  if (actionable.length === 0) {
1883
2099
  const t = resolveInstallTargets(scope);
@@ -1969,7 +2185,7 @@ function readWorkspaceConfigSafe(ws) {
1969
2185
  }
1970
2186
  }
1971
2187
  async function buildInstallPlan(client, scope, projectId, only) {
1972
- const listQuery = scope === "global" ? { scope: "global" } : { scope: "project", ...projectId ? { projectId } : {} };
2188
+ const listQuery = scope === "global" ? { scope: "global", includeDisabled: true } : { scope: "project", ...projectId ? { projectId } : {}, includeDisabled: true };
1973
2189
  const skillsR = await handleListSkills(client, listQuery);
1974
2190
  const agentsR = await handleListAgents(client, listQuery);
1975
2191
  if (!skillsR.success) return skillsR;
@@ -2005,6 +2221,7 @@ async function buildInstallPlan(client, scope, projectId, only) {
2005
2221
  function compareSkill(s, dir) {
2006
2222
  const path = skillTargetPath(dir, s);
2007
2223
  const base = { name: s.name, type: "skill", serverVersion: s.version, action: "install", reason: "" };
2224
+ if (s.enabled === false) return { ...base, action: "skip", reason: "server asset disabled", disabled: true };
2008
2225
  if (!isSafeAssetName(s.name)) {
2009
2226
  return { ...base, action: "conflict", reason: `unsafe asset name "${s.name}"` };
2010
2227
  }
@@ -2022,6 +2239,7 @@ function compareSkill(s, dir) {
2022
2239
  function compareAgent(a, dir) {
2023
2240
  const path = agentTargetPath(dir, a);
2024
2241
  const base = { name: a.name, type: "agent", serverVersion: a.version, action: "install", reason: "" };
2242
+ if (a.enabled === false) return { ...base, action: "skip", reason: "server asset disabled", disabled: true };
2025
2243
  if (!isSafeAssetName(a.name)) {
2026
2244
  return { ...base, action: "conflict", reason: `unsafe asset name "${a.name}"` };
2027
2245
  }
@@ -2079,7 +2297,7 @@ async function applyInstall(client, scope, projectId, items, opts) {
2079
2297
  const results = [];
2080
2298
  const force = opts?.force ?? false;
2081
2299
  const actionable = items.filter(
2082
- (i) => force || i.action === "install" || i.action === "update"
2300
+ (i) => !i.disabled && (force || i.action === "install" || i.action === "update")
2083
2301
  );
2084
2302
  const assetQuery = scope === "global" ? { scope: "global" } : { scope: "project", ...projectId ? { projectId } : {} };
2085
2303
  for (const item of actionable) {
@@ -2113,9 +2331,22 @@ async function applyInstall(client, scope, projectId, items, opts) {
2113
2331
  continue;
2114
2332
  }
2115
2333
  const targetPath = skillTargetPath(targets.dir, r.data);
2334
+ const invalidRef = validateReferencesLocally(SKILL_MAIN_DOC3, r.data.references);
2335
+ if (invalidRef !== null) {
2336
+ results.push({ name: item.name, type: "skill", action: "failed", reason: `invalid reference doc from server: ${invalidRef}`, hint: "\u5F15\u7528\u6587\u6863\u975E\u6CD5\uFF08\u6570\u636E\u53EF\u80FD\u88AB\u7ED5\u8FC7\u6821\u9A8C\u5199\u5165\uFF09\uFF1B\u4FEE\u6B63 server \u6570\u636E\u540E\u91CD\u8BD5\uFF0C\u672C\u6761\u672A\u5199\u5165" });
2337
+ continue;
2338
+ }
2116
2339
  const targetExists = existsSync5(targetPath);
2117
- writeFile(targetPath, skillToMarkdown(r.data));
2118
- results.push({ name: item.name, type: "skill", action: targetExists ? "updated" : "installed" });
2340
+ writeAssetDirectory(dirname3(targetPath), [
2341
+ { relPath: SKILL_MAIN_DOC3, content: skillToMarkdown(r.data) },
2342
+ ...(r.data.references ?? []).map((ref) => ({ relPath: ref.path, content: ref.content }))
2343
+ ]);
2344
+ results.push({
2345
+ name: item.name,
2346
+ type: "skill",
2347
+ action: targetExists ? "updated" : "installed",
2348
+ ...r.data.references?.length ? { reason: `${String(r.data.references.length)} reference doc(s) synced` } : {}
2349
+ });
2119
2350
  } else {
2120
2351
  if (!isSafeAssetName(item.name)) {
2121
2352
  results.push({ name: item.name, type: "agent", action: "failed", reason: `unsafe asset name "${item.name}"`, hint: 'asset name must not contain path separators or "." / ".." segments' });
@@ -2136,9 +2367,22 @@ async function applyInstall(client, scope, projectId, items, opts) {
2136
2367
  continue;
2137
2368
  }
2138
2369
  const targetPath = agentTargetPath(targets.dir, r.data);
2370
+ const invalidRef = validateReferencesLocally(AGENT_MAIN_DOC3, r.data.references);
2371
+ if (invalidRef !== null) {
2372
+ results.push({ name: item.name, type: "agent", action: "failed", reason: `invalid reference doc from server: ${invalidRef}`, hint: "\u5F15\u7528\u6587\u6863\u975E\u6CD5\uFF08\u6570\u636E\u53EF\u80FD\u88AB\u7ED5\u8FC7\u6821\u9A8C\u5199\u5165\uFF09\uFF1B\u4FEE\u6B63 server \u6570\u636E\u540E\u91CD\u8BD5\uFF0C\u672C\u6761\u672A\u5199\u5165" });
2373
+ continue;
2374
+ }
2139
2375
  const targetExists = existsSync5(targetPath);
2140
- writeFile(targetPath, agentToMarkdown(r.data, realModel));
2141
- results.push({ name: item.name, type: "agent", action: targetExists ? "updated" : "installed" });
2376
+ writeAssetDirectory(dirname3(targetPath), [
2377
+ { relPath: AGENT_MAIN_DOC3, content: agentToMarkdown(r.data, realModel) },
2378
+ ...(r.data.references ?? []).map((ref) => ({ relPath: ref.path, content: ref.content }))
2379
+ ]);
2380
+ results.push({
2381
+ name: item.name,
2382
+ type: "agent",
2383
+ action: targetExists ? "updated" : "installed",
2384
+ ...r.data.references?.length ? { reason: `${String(r.data.references.length)} reference doc(s) synced` } : {}
2385
+ });
2142
2386
  }
2143
2387
  } catch (e) {
2144
2388
  results.push({ name: item.name, type: item.type, action: "failed", reason: e instanceof Error ? e.message : String(e), hint: "\u68C0\u67E5\u76EE\u6807\u76EE\u5F55\u6743\u9650\u540E\u91CD\u8BD5\uFF1B\u5DF2\u5199\u5165\u6761\u76EE\u4E0D\u53D7\u5F71\u54CD\uFF08\u5E42\u7B49\uFF0C\u4FEE\u590D\u540E\u91CD\u8DD1\u81EA\u6108\uFF09" });
@@ -2152,12 +2396,12 @@ function buildInstallGuidance(scope, targets) {
2152
2396
  const lines = [];
2153
2397
  lines.push("\u2500\u2500 siming \u901A\u7528\u8D44\u4EA7\u8FC1\u79FB\u6307\u5F15\uFF08.agents \u5F00\u653E\u534F\u8BAE\u843D\u70B9\uFF09\u2500\u2500");
2154
2398
  lines.push(`[1] \u8D44\u4EA7\u4F4D\u7F6E\uFF08${scope === "global" ? "\u7528\u6237\u7EA7" : "\u9879\u76EE\u7EA7"} ${targets.dir}\uFF09\uFF1A`);
2155
- lines.push(` - skills: ${join5(targets.dir, "skills")}\uFF08\u6BCF\u4E2A skill \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF0C\u542B SKILL.md\uFF09`);
2156
- lines.push(` - agents: ${join5(targets.dir, "agents")}\uFF08\u6BCF\u4E2A agent \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF0C\u542B agent.md\uFF09`);
2399
+ lines.push(` - skills: ${join5(targets.dir, "skills")}\uFF08\u6BCF\u4E2A skill \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF0C\u542B SKILL.md \u4E0E\u5176\u5F15\u7528\u6587\u6863\uFF09`);
2400
+ lines.push(` - agents: ${join5(targets.dir, "agents")}\uFF08\u6BCF\u4E2A agent \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF0C\u542B agent.md \u4E0E\u5176\u5F15\u7528\u6587\u6863\uFF09`);
2157
2401
  if (targets.mcpConfigPath) {
2158
2402
  lines.push(` - MCP \u6CE8\u518C: ${targets.mcpConfigPath}\uFF08\u9876\u5C42 mcpServers.siming \u2192 stdio \u547D\u4EE4 "siming mcp-serve"\uFF09`);
2159
2403
  }
2160
- lines.push("[2] \u5F15\u7528\u65B9\u5F0F\uFF1Askill = \u5B50\u76EE\u5F55\u5185 SKILL.md\uFF08frontmatter name/description\uFF09\uFF1Bagent = \u5B50\u76EE\u5F55\u5185 agent.md\uFF08frontmatter description/model/skills\uFF0C\u6B63\u6587\u542B\u7ED1\u5B9A Skill \u52A0\u8F7D\u6307\u4EE4\uFF09\u3002");
2404
+ lines.push("[2] \u5F15\u7528\u65B9\u5F0F\uFF1Askill = \u5B50\u76EE\u5F55\u5185 SKILL.md\uFF08frontmatter name/description\uFF09\uFF1Bagent = \u5B50\u76EE\u5F55\u5185 agent.md\uFF08frontmatter description/model/skills\uFF0C\u6B63\u6587\u542B\u7ED1\u5B9A Skill \u52A0\u8F7D\u6307\u4EE4\uFF09\uFF1B\u5E26\u5F15\u7528\u6587\u6863\u7684\u8D44\u4EA7\uFF0C\u4E3B\u6587\u6863\u4E2D\u7684\u76F8\u5BF9\u8DEF\u5F84\u5F15\u7528\u5728\u5B50\u76EE\u5F55\u5185\u76F4\u63A5\u53EF\u8FBE\u3002");
2161
2405
  const mcpPart = targets.mcpConfigPath ? "\uFF1B\u628A mcpServers.siming \u6761\u76EE\u5408\u5E76\u8FDB\u672C\u5DE5\u5177\u7684 MCP \u914D\u7F6E" : "\uFF08\u9879\u76EE\u7EA7\u5B89\u88C5\u4E0D\u542B MCP \u6CE8\u518C\uFF0C\u9700\u8981\u65F6\u53E6\u884C\u6267\u884C\u7528\u6237\u7EA7 install\uFF09";
2162
2406
  lines.push(`[3] \u6CE8\u518C\u9014\u5F84\uFF08\u5F53\u524D\u7F16\u7A0B\u5DE5\u5177\u4F1A\u8BDD\u4E2D\u7684 AI \u53EF\u76F4\u63A5\u6267\u884C\uFF09\uFF1A\u628A skills \u5B50\u76EE\u5F55\u52A0\u5165\u672C\u5DE5\u5177\u7684 skill \u641C\u7D22\u8DEF\u5F84\uFF1B\u628A agent \u5B50\u76EE\u5F55\u6CE8\u518C\u8FDB\u672C\u5DE5\u5177\u7684 subagent \u914D\u7F6E${mcpPart}\u3002`);
2163
2407
  if (targets.mcpConfigPath) {
@@ -2174,10 +2418,6 @@ async function resolveAgentModel(client, agent) {
2174
2418
  const alias = r.data.find((a) => a.code === agent.model);
2175
2419
  return alias?.realModel ?? null;
2176
2420
  }
2177
- function writeFile(path, content) {
2178
- mkdirSync4(dirname3(path), { recursive: true });
2179
- writeFileSync4(path, content, "utf-8");
2180
- }
2181
2421
  function renderInstallPlan(format, plan, scope, targets) {
2182
2422
  if (format === "json") {
2183
2423
  renderResult("json", { success: true, data: { scope, ...targets ? { dir: targets.dir, mcpConfigPath: targets.mcpConfigPath } : {}, items: plan.items } });
@@ -2431,7 +2671,7 @@ function createDoctorCommand() {
2431
2671
  // src/mcp/server.ts
2432
2672
  function mcpContent(result) {
2433
2673
  const payload = result.success ? result.data : result.error;
2434
- const text = payload === void 0 ? "null" : JSON.stringify(payload, null, 2);
2674
+ const text = payload === void 0 ? "null" : JSON.stringify(payload);
2435
2675
  return result.success ? { content: [{ type: "text", text }] } : { content: [{ type: "text", text }], isError: true };
2436
2676
  }
2437
2677
  function requireError(action, fields, args) {
@@ -2457,7 +2697,7 @@ function createMcpServer() {
2457
2697
  const currentProcessUrl = resolveServerUrl();
2458
2698
  server.tool(
2459
2699
  "siming_task",
2460
- "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\uFF0C\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\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)\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\u2014\u2014\u63A8\u8FDB\u4EFB\u52A1\u524D\u4F18\u5148\u8C03\u7528)\uFF1Bnode(taskId,view=prompt|skills\uFF1BnodeId \u7F3A\u7701\u7528\u5F53\u524D\u8282\u70B9)\uFF1Badvance(taskId\uFF1Bnote \u5199 history\u3001summary \u5199 nodeRecords\uFF0C\u4E24\u4F4D\u72EC\u7ACB)\uFF1Bapprove(taskId,decision=approved|rejected\uFF1B\u53EF\u9009 comment)\uFF1Bpause(taskId\uFF1B\u53EF\u9009 reason)\uFF1Bresume(taskId\uFF1B\u53EF\u9009 resumeNote)\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)\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",
2700
+ "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\uFF0C\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\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",
2461
2701
  taskArgs,
2462
2702
  async (args) => {
2463
2703
  switch (args.action) {
@@ -2491,15 +2731,27 @@ function createMcpServer() {
2491
2731
  );
2492
2732
  }
2493
2733
  case "context": {
2494
- const { taskId } = args;
2734
+ const { taskId, view } = args;
2495
2735
  if (taskId === void 0) return requireError("context", ["taskId"], args);
2496
- return mcpContent(await handleGetContext(client, taskId));
2736
+ if (view !== void 0 && view !== "basic" && view !== "full") {
2737
+ return localError(
2738
+ `action=context \u7684 view \u53EA\u63A5\u53D7 basic|full\uFF08\u6536\u5230 '${view}'\u2014\u2014prompt/skills \u5C5E node action\uFF09`,
2739
+ "view \u503C\u968F action \u4E0D\u540C\uFF1Acontext\u2192basic|full\uFF08\u7F3A\u7701 basic\uFF0C\u4E0D\u643A\u5E26 artifact \u5168\u6587\u5FEB\u7167\uFF09\uFF1Bnode\u2192prompt|skills"
2740
+ );
2741
+ }
2742
+ return mcpContent(await handleGetContext(client, taskId, view));
2497
2743
  }
2498
2744
  case "node": {
2499
2745
  const { taskId, view } = args;
2500
2746
  if (taskId === void 0 || view === void 0) {
2501
2747
  return requireError("node", ["taskId", "view"], args);
2502
2748
  }
2749
+ if (view !== "prompt" && view !== "skills") {
2750
+ return localError(
2751
+ `action=node \u7684 view \u53EA\u63A5\u53D7 prompt|skills\uFF08\u6536\u5230 '${view}'\u2014\u2014basic/full \u5C5E context action\uFF09`,
2752
+ "view \u503C\u968F action \u4E0D\u540C\uFF1Anode\u2192prompt|skills\uFF1Bcontext\u2192basic|full"
2753
+ );
2754
+ }
2503
2755
  let nodeId = args.nodeId;
2504
2756
  if (!nodeId) {
2505
2757
  const q = await handleQueryState(client, taskId);
@@ -2535,6 +2787,11 @@ function createMcpServer() {
2535
2787
  if (taskId === void 0) return requireError("resume", ["taskId"], args);
2536
2788
  return mcpContent(await handleResume(client, taskId, args.resumeNote));
2537
2789
  }
2790
+ case "cancel": {
2791
+ const { taskId } = args;
2792
+ if (taskId === void 0) return requireError("cancel", ["taskId"], args);
2793
+ return mcpContent(await handleCancel(client, taskId, args.reason));
2794
+ }
2538
2795
  case "history": {
2539
2796
  const { taskId } = args;
2540
2797
  if (taskId === void 0) return requireError("history", ["taskId"], args);
@@ -2590,7 +2847,7 @@ function createMcpServer() {
2590
2847
  let fullText = content;
2591
2848
  if (file) {
2592
2849
  try {
2593
- fullText = readFileSync6(file, "utf-8");
2850
+ fullText = readFileSync7(file, "utf-8");
2594
2851
  } catch (e) {
2595
2852
  return localError(`\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25: ${file}\uFF08${e instanceof Error ? e.message : String(e)}\uFF09`);
2596
2853
  }
@@ -2671,7 +2928,7 @@ function createMcpServer() {
2671
2928
  );
2672
2929
  server.tool(
2673
2930
  "siming_template",
2674
- "DAG \u6A21\u677F\u7BA1\u7406\u3002action\uFF1Alist=\u6A21\u677F\u5217\u8868\uFF08\u6982\u8981\u6295\u5F71\uFF0C\u4E0D\u542B prompt \u5168\u6587\uFF09\uFF1Bshow=\u6A21\u677F\u8BE6\u60C5\uFF08\u542B\u5168\u90E8\u8282\u70B9 prompt\uFF0C\u4EC5\u5B9E\u9645\u7F16\u6392\u65F6\u7528\uFF09\uFF1Bimport=\u5BFC\u5165\u6A21\u677F\uFF08yaml \u5B57\u7B26\u4E32\u76F4\u4F20\uFF0CprojectId \u7F3A\u7701\u7528 YAML \u5185\u503C\uFF0Cname \u53EF\u8986\u76D6\u6A21\u677F\u540D\uFF09\u3002",
2931
+ "DAG \u6A21\u677F\u7BA1\u7406\u3002action\uFF1Alist=\u6A21\u677F\u5217\u8868\uFF08\u6982\u8981\u6295\u5F71\uFF0C\u4E0D\u542B prompt \u5168\u6587\uFF09\uFF1Bshow=\u6A21\u677F\u8BE6\u60C5\uFF08\u542B\u5168\u90E8\u8282\u70B9 prompt\uFF0C\u4EC5\u5B9E\u9645\u7F16\u6392\u65F6\u7528\uFF09\uFF1Bimport=\u5BFC\u5165\u6A21\u677F\uFF08yaml \u5B57\u7B26\u4E32\u76F4\u4F20\uFF0CprojectId \u7F3A\u7701\u7528 YAML \u5185\u503C\uFF0Cname \u53EF\u8986\u76D6\u6A21\u677F\u540D\uFF09\u3002\u505C\u7528\u6A21\u677F\uFF08Web \u7BA1\u7406\u53F0\u542F\u505C\uFF09\uFF1Alist \u9ED8\u8BA4\u4E0D\u542B\u505C\u7528\u6A21\u677F\uFF1Bshow \u6309 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",
2675
2932
  templateArgs,
2676
2933
  async (args) => {
2677
2934
  switch (args.action) {
@@ -2711,7 +2968,7 @@ function createMcpServer() {
2711
2968
  );
2712
2969
  server.tool(
2713
2970
  "siming_skill",
2714
- "skill \u8D44\u4EA7\u7BA1\u7406\u3002action\uFF1Alist\uFF08scope/projectId \u8FC7\u6EE4\uFF09\uFF1Bshow\uFF08name\uFF09\uFF1Bcreate\uFF08name/description/content/category/scope\uFF0Cscope=project \u9700 projectId\uFF09\uFF1Bupdate\uFF08name + \u5F85\u66F4\u65B0\u5B57\u6BB5\uFF0C\u591A\u503C\u5B57\u6BB5\u6574\u4F53\u66FF\u6362\uFF09\uFF1Bcopy\uFF08name/newName/newScope\uFF0CnewScope=project \u9700 targetProjectId\uFF09\uFF1Bdelete\uFF08name\uFF09\u3002",
2971
+ `skill \u8D44\u4EA7\u7BA1\u7406\u3002action\uFF1Alist\uFF08scope/projectId \u8FC7\u6EE4\uFF09\uFF1Bshow\uFF08name\uFF09\uFF1Bcreate\uFF08name/description/content/category/scope\uFF0Cscope=project \u9700 projectId\uFF09\uFF1Bupdate\uFF08name + \u5F85\u66F4\u65B0\u5B57\u6BB5\uFF0C\u591A\u503C\u5B57\u6BB5\u6574\u4F53\u66FF\u6362\uFF09\uFF1Bcopy\uFF08name/newName/newScope\uFF0CnewScope=project \u9700 targetProjectId\uFF09\uFF1Bdelete\uFF08name\uFF09\u3002references\uFF08\u53EF\u9009\uFF09\uFF1A\u5F15\u7528\u6587\u6863\u96C6\u5408 [{path, content}]\u2014\u2014path \u4E3A\u76F8\u5BF9\u8D44\u4EA7\u6839\u7684\u6B63\u659C\u6760\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u7981\u7EDD\u5BF9\u8DEF\u5F84/.. \u56DE\u6EAF/\u53CD\u659C\u6760/\u7A7A\u6BB5/\u4E0E\u4E3B\u6587\u6863\u540D ${"SKILL.md"} \u51B2\u7A81\uFF08\u5927\u5C0F\u5199\u4E0D\u654F\u611F\uFF09/\u8DEF\u5F84\u4E92\u4E3A\u76EE\u5F55\u524D\u7F00\uFF1B\u4E0A\u9650\uFF1A\u5355\u8D44\u4EA7 20 \u6761\u3001\u5355\u6587\u6863 100 \u4E07\u5B57\u7B26\u3001\u4E3B\u6587\u6863+\u5F15\u7528\u603B\u91CF 300 \u4E07\u5B57\u7B26\u3002create \u65F6 references \u5373\u521D\u59CB\u96C6\u5408\uFF1Bupdate \u4E24\u6001\u8BED\u4E49\uFF1A\u7F3A\u7701 references \u4E14 clearRefs \u672A\u4F20 = \u4E0D\u4FEE\u6539\u73B0\u6709\u5F15\u7528\uFF08\u91CD\u8981\uFF1A\u5355\u6587\u4EF6\u66F4\u65B0\u52FF\u4F20 [] \u4EE5\u514D\u8BEF\u6E05\u7A7A\uFF09\u3001references=[] \u6216 clearRefs=true = \u6E05\u7A7A\u5168\u90E8\u3001references=\u975E\u7A7A\u6570\u7EC4 = \u6574\u7B14\u66FF\u6362\uFF1BclearRefs \u4E0E references \u4E92\u65A5\u3002\u5220\u9664\u4FDD\u62A4\uFF1Aupdate \u79FB\u9664\u7684\u5F15\u7528\u6587\u6863 path \u82E5\u4ECD\u51FA\u73B0\u5728\u63D0\u4EA4\u7684\u4E3B\u6587\u6863\u6B63\u6587\u4E2D\uFF0C\u670D\u52A1\u7AEF\u62D2\u7EDD\uFF08409 REFERENCE_IN_USE\uFF09\uFF0C\u9700\u5148\u79FB\u9664\u6B63\u6587\u4E2D\u7684\u5F15\u7528\u518D\u5220\u3002\u505C\u7528\u8D44\u4EA7\uFF08enabled=false\uFF0CWeb \u7BA1\u7406\u53F0\u542F\u505C\uFF09\uFF1Alist \u9ED8\u8BA4\u4E0D\u542B\u505C\u7528\u6761\u76EE\uFF1Bshow\uFF08\u6309\u540D\u5355\u5BFB\u5740\uFF09\u8FD4\u56DE 404\uFF08\u4E0E\u4E0D\u5B58\u5728\u540C\u5F62\uFF09\uFF1Bupdate/delete/copy \u4E0D\u53D7\u542F\u505C\u5F71\u54CD\uFF08\u5199\u901A\u9053\u653E\u884C\uFF0C\u526F\u672C\u9ED8\u8BA4\u542F\u7528\uFF09\uFF1B\u91CD\u65B0\u542F\u7528\u540E\u6062\u590D\u53EF\u89C1\u3002`,
2715
2972
  skillArgs,
2716
2973
  async (args) => {
2717
2974
  switch (args.action) {
@@ -2749,6 +3006,7 @@ function createMcpServer() {
2749
3006
  category,
2750
3007
  scope,
2751
3008
  version: "1.0.0",
3009
+ ...args.references !== void 0 ? { references: args.references } : {},
2752
3010
  ...args.projectId !== void 0 ? { projectId: args.projectId } : {}
2753
3011
  })
2754
3012
  );
@@ -2756,11 +3014,23 @@ function createMcpServer() {
2756
3014
  case "update": {
2757
3015
  const { name } = args;
2758
3016
  if (name === void 0) return requireError("update", ["name"], args);
2759
- const hasAny = args.description !== void 0 || args.content !== void 0 || args.category !== void 0 || args.version !== void 0 || args.scope !== void 0 || args.projectId !== void 0;
3017
+ if (args.clearRefs === true && args.references !== void 0) {
3018
+ return localError(
3019
+ "action=update \u7684 clearRefs \u4E0E references \u4E92\u65A5",
3020
+ "\u6E05\u7A7A\u5168\u90E8\u5F15\u7528\u6587\u6863\u7528 clearRefs=true \u6216 references=[]\uFF1B\u6574\u7B14\u66FF\u6362\u7528 references=\u5B8C\u6574\u6570\u7EC4"
3021
+ );
3022
+ }
3023
+ let resolvedRefs;
3024
+ if (args.clearRefs === true) {
3025
+ resolvedRefs = [];
3026
+ } else if (args.references !== void 0) {
3027
+ resolvedRefs = args.references;
3028
+ }
3029
+ const hasAny = args.description !== void 0 || args.content !== void 0 || args.category !== void 0 || args.version !== void 0 || args.scope !== void 0 || args.projectId !== void 0 || resolvedRefs !== void 0;
2760
3030
  if (!hasAny) {
2761
3031
  return localError(
2762
- "action=update \u9700\u8981\u81F3\u5C11\u4E00\u4E2A\u5F85\u66F4\u65B0\u5B57\u6BB5\uFF08description/content/category/version/scope/projectId\uFF09",
2763
- "\u591A\u503C\u8BED\u4E49\u5B57\u6BB5\u6574\u4F53\u66FF\u6362\uFF0C\u6F0F\u4F20 = \u6E05\u7A7A"
3032
+ "action=update \u9700\u8981\u81F3\u5C11\u4E00\u4E2A\u5F85\u66F4\u65B0\u5B57\u6BB5\uFF08description/content/category/version/scope/projectId/references\uFF09",
3033
+ "\u591A\u503C\u8BED\u4E49\u5B57\u6BB5\u6574\u4F53\u66FF\u6362\uFF1Breferences \u7F3A\u7701 = \u4E0D\u4FEE\u6539\u73B0\u6709\u5F15\u7528"
2764
3034
  );
2765
3035
  }
2766
3036
  return mcpContent(
@@ -2770,6 +3040,7 @@ function createMcpServer() {
2770
3040
  ...args.category !== void 0 ? { category: args.category } : {},
2771
3041
  ...args.version !== void 0 ? { version: args.version } : {},
2772
3042
  ...args.scope !== void 0 ? { scope: args.scope } : {},
3043
+ ...resolvedRefs !== void 0 ? { references: resolvedRefs } : {},
2773
3044
  ...args.projectId !== void 0 ? { projectId: args.projectId } : {}
2774
3045
  })
2775
3046
  );
@@ -2800,7 +3071,7 @@ function createMcpServer() {
2800
3071
  );
2801
3072
  server.tool(
2802
3073
  "siming_agent",
2803
- "agent \u8D44\u4EA7\u7BA1\u7406\u3002action\uFF1Alist\uFF08scope/projectId \u8FC7\u6EE4\uFF09\uFF1Bshow\uFF08name\uFF09\uFF1Bcreate\uFF08name/description/systemPrompt/model/scope\uFF0Cscope=project \u9700 projectId\uFF1BboundSkills/tools/permissions \u53EF\u9009\uFF09\uFF1Bupdate\uFF08name + \u5F85\u66F4\u65B0\u5B57\u6BB5\uFF0CboundSkills/tools/permissions \u4E3A\u6574\u4F53\u66FF\u6362\u8BED\u4E49\uFF09\uFF1Bcopy\uFF08name/newName/newScope\uFF0CnewScope=project \u9700 targetProjectId\uFF09\uFF1Bdelete\uFF08name\uFF09\u3002\u5168\u5C40 agent \u4EC5\u53EF\u7ED1\u5B9A\u5168\u5C40 skill\u3002tools/permissions \u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4\u3001\u65E0\u670D\u52A1\u7AEF\u503C\u57DF\u6821\u9A8C\u2014\u2014\u8BED\u4E49\u662F\u8D44\u4EA7\u5B89\u88C5\u5230\u7F16\u7A0B\u5DE5\u5177\u65F6\u5EFA\u8BAE\u6388\u4E88\u8BE5 agent \u7684\u5DE5\u5177\u540D/\u6743\u9650\u6E05\u5355\uFF0C\u7531\u5BBF\u4E3B\u4FA7\u89E3\u91CA\uFF1Bmodel \u987B\u4E3A\u5DF2\u6CE8\u518C model alias code\uFF08\u53EF\u7528\u503C\u7ECF model \u6620\u5C04\u7BA1\u7406\uFF0C\u672A\u6CE8\u518C\u521B\u5EFA\u88AB\u62D2\uFF09\u3002",
3074
+ `agent \u8D44\u4EA7\u7BA1\u7406\u3002action\uFF1Alist\uFF08scope/projectId \u8FC7\u6EE4\uFF09\uFF1Bshow\uFF08name\uFF09\uFF1Bcreate\uFF08name/description/systemPrompt/model/scope\uFF0Cscope=project \u9700 projectId\uFF1BboundSkills/tools/permissions \u53EF\u9009\uFF09\uFF1Bupdate\uFF08name + \u5F85\u66F4\u65B0\u5B57\u6BB5\uFF0CboundSkills/tools/permissions \u4E3A\u6574\u4F53\u66FF\u6362\u8BED\u4E49\uFF09\uFF1Bcopy\uFF08name/newName/newScope\uFF0CnewScope=project \u9700 targetProjectId\uFF09\uFF1Bdelete\uFF08name\uFF09\u3002\u5168\u5C40 agent \u4EC5\u53EF\u7ED1\u5B9A\u5168\u5C40 skill\u3002function\uFF08\u53EF\u9009\uFF09\uFF1Areviewer|executor\uFF0C\u7F3A\u7701 executor\uFF08T202608260002\uFF09\u2014\u2014\u529F\u80FD\u7C7B\u578B\u4EC5\u5F71\u54CD siming install \u843D\u76D8\u7684\u4FE1\u606F\u8FB9\u754C\u6CE8\u5165\uFF1Areviewer \u843D\u76D8\u4EA7\u7269\u6B63\u6587\u5934\u6CE8\u5165\u53D7\u9650\u4F9D\u636E\u58F0\u660E\uFF0Cexecutor \u4E0D\u6CE8\u5165\uFF1Bfunction \u53D8\u66F4\u65F6\u670D\u52A1\u7AEF\u81EA\u52A8\u9012\u589E\u7248\u672C\u4EE5\u4F20\u64AD\u5DF2\u88C5\u73AF\u5883\u3002tools/permissions \u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4\u3001\u65E0\u670D\u52A1\u7AEF\u503C\u57DF\u6821\u9A8C\u2014\u2014\u8BED\u4E49\u662F\u8D44\u4EA7\u5B89\u88C5\u5230\u7F16\u7A0B\u5DE5\u5177\u65F6\u5EFA\u8BAE\u6388\u4E88\u8BE5 agent \u7684\u5DE5\u5177\u540D/\u6743\u9650\u6E05\u5355\uFF0C\u7531\u5BBF\u4E3B\u4FA7\u89E3\u91CA\uFF1Bmodel \u987B\u4E3A\u5DF2\u6CE8\u518C model alias code\uFF08\u53EF\u7528\u503C\u7ECF model \u6620\u5C04\u7BA1\u7406\uFF0C\u672A\u6CE8\u518C\u521B\u5EFA\u88AB\u62D2\uFF09\u3002references\uFF08\u53EF\u9009\uFF09\uFF1A\u5F15\u7528\u6587\u6863\u96C6\u5408 [{path, content}]\u2014\u2014path \u4E3A\u76F8\u5BF9\u8D44\u4EA7\u6839\u7684\u6B63\u659C\u6760\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u7981\u7EDD\u5BF9\u8DEF\u5F84/.. \u56DE\u6EAF/\u53CD\u659C\u6760/\u7A7A\u6BB5/\u4E0E\u4E3B\u6587\u6863\u540D ${"agent.md"} \u51B2\u7A81\uFF08\u5927\u5C0F\u5199\u4E0D\u654F\u611F\uFF09/\u8DEF\u5F84\u4E92\u4E3A\u76EE\u5F55\u524D\u7F00\uFF1B\u4E0A\u9650\uFF1A\u5355\u8D44\u4EA7 20 \u6761\u3001\u5355\u6587\u6863 100 \u4E07\u5B57\u7B26\u3001\u4E3B\u6587\u6863+\u5F15\u7528\u603B\u91CF 300 \u4E07\u5B57\u7B26\u3002create \u65F6 references \u5373\u521D\u59CB\u96C6\u5408\uFF1Bupdate \u4E24\u6001\u8BED\u4E49\uFF1A\u7F3A\u7701 references \u4E14 clearRefs \u672A\u4F20 = \u4E0D\u4FEE\u6539\u73B0\u6709\u5F15\u7528\u3001references=[] \u6216 clearRefs=true = \u6E05\u7A7A\u5168\u90E8\u3001references=\u975E\u7A7A\u6570\u7EC4 = \u6574\u7B14\u66FF\u6362\uFF1BclearRefs \u4E0E references \u4E92\u65A5\u3002\u5220\u9664\u4FDD\u62A4\uFF1Aupdate \u79FB\u9664\u7684\u5F15\u7528\u6587\u6863 path \u82E5\u4ECD\u51FA\u73B0\u5728\u63D0\u4EA4\u7684 systemPrompt \u6B63\u6587\u4E2D\uFF0C\u670D\u52A1\u7AEF\u62D2\u7EDD\uFF08409 REFERENCE_IN_USE\uFF09\uFF0C\u9700\u5148\u79FB\u9664\u6B63\u6587\u4E2D\u7684\u5F15\u7528\u518D\u5220\u3002\u505C\u7528\u8D44\u4EA7\uFF08enabled=false\uFF0CWeb \u7BA1\u7406\u53F0\u542F\u505C\uFF09\uFF1Alist \u9ED8\u8BA4\u4E0D\u542B\u505C\u7528\u6761\u76EE\uFF1Bshow\uFF08\u6309\u540D\u5355\u5BFB\u5740\uFF09\u8FD4\u56DE 404\uFF08\u4E0E\u4E0D\u5B58\u5728\u540C\u5F62\uFF09\uFF1Bupdate/delete/copy \u4E0D\u53D7\u542F\u505C\u5F71\u54CD\uFF08\u5199\u901A\u9053\u653E\u884C\uFF0C\u526F\u672C\u9ED8\u8BA4\u542F\u7528\uFF09\uFF1B\u91CD\u65B0\u542F\u7528\u540E\u6062\u590D\u53EF\u89C1\u3002`,
2804
3075
  agentArgs,
2805
3076
  async (args) => {
2806
3077
  switch (args.action) {
@@ -2838,9 +3109,12 @@ function createMcpServer() {
2838
3109
  model,
2839
3110
  scope,
2840
3111
  version: "1.0.0",
3112
+ // function 缺省 executor(AgentCreate 输出类型必有,与 API 缺省归一一致)
3113
+ "function": args["function"] ?? "executor",
2841
3114
  boundSkills: args.boundSkills ?? [],
2842
3115
  tools: args.tools ?? [],
2843
3116
  permissions: args.permissions ?? [],
3117
+ ...args.references !== void 0 ? { references: args.references } : {},
2844
3118
  ...args.projectId !== void 0 ? { projectId: args.projectId } : {}
2845
3119
  })
2846
3120
  );
@@ -2848,11 +3122,23 @@ function createMcpServer() {
2848
3122
  case "update": {
2849
3123
  const { name } = args;
2850
3124
  if (name === void 0) return requireError("update", ["name"], args);
2851
- const hasAny = args.description !== void 0 || args.systemPrompt !== void 0 || args.model !== void 0 || args.scope !== void 0 || args.projectId !== void 0 || args.boundSkills !== void 0 || args.tools !== void 0 || args.permissions !== void 0;
3125
+ if (args.clearRefs === true && args.references !== void 0) {
3126
+ return localError(
3127
+ "action=update \u7684 clearRefs \u4E0E references \u4E92\u65A5",
3128
+ "\u6E05\u7A7A\u5168\u90E8\u5F15\u7528\u6587\u6863\u7528 clearRefs=true \u6216 references=[]\uFF1B\u6574\u7B14\u66FF\u6362\u7528 references=\u5B8C\u6574\u6570\u7EC4"
3129
+ );
3130
+ }
3131
+ let resolvedRefs;
3132
+ if (args.clearRefs === true) {
3133
+ resolvedRefs = [];
3134
+ } else if (args.references !== void 0) {
3135
+ resolvedRefs = args.references;
3136
+ }
3137
+ const hasAny = args.description !== void 0 || args.systemPrompt !== void 0 || args.model !== void 0 || args.scope !== void 0 || args.projectId !== void 0 || args.boundSkills !== void 0 || args.tools !== void 0 || args.permissions !== void 0 || args["function"] !== void 0 || resolvedRefs !== void 0;
2852
3138
  if (!hasAny) {
2853
3139
  return localError(
2854
- "action=update \u9700\u8981\u81F3\u5C11\u4E00\u4E2A\u5F85\u66F4\u65B0\u5B57\u6BB5\uFF08description/systemPrompt/model/scope/projectId/boundSkills/tools/permissions\uFF09",
2855
- "boundSkills/tools/permissions \u4E3A\u6574\u4F53\u66FF\u6362\u8BED\u4E49\uFF0C\u6F0F\u4F20 = \u6E05\u7A7A"
3140
+ "action=update \u9700\u8981\u81F3\u5C11\u4E00\u4E2A\u5F85\u66F4\u65B0\u5B57\u6BB5\uFF08description/systemPrompt/model/scope/projectId/boundSkills/tools/permissions/function/references\uFF09",
3141
+ "boundSkills/tools/permissions \u4E3A\u6574\u4F53\u66FF\u6362\u8BED\u4E49\uFF0C\u6F0F\u4F20 = \u6E05\u7A7A\uFF1Breferences \u7F3A\u7701 = \u4E0D\u4FEE\u6539\u73B0\u6709\u5F15\u7528"
2856
3142
  );
2857
3143
  }
2858
3144
  return mcpContent(
@@ -2864,7 +3150,9 @@ function createMcpServer() {
2864
3150
  ...args.projectId !== void 0 ? { projectId: args.projectId } : {},
2865
3151
  ...args.boundSkills !== void 0 ? { boundSkills: args.boundSkills } : {},
2866
3152
  ...args.tools !== void 0 ? { tools: args.tools } : {},
2867
- ...args.permissions !== void 0 ? { permissions: args.permissions } : {}
3153
+ ...args.permissions !== void 0 ? { permissions: args.permissions } : {},
3154
+ ...args["function"] !== void 0 ? { "function": args["function"] } : {},
3155
+ ...resolvedRefs !== void 0 ? { references: resolvedRefs } : {}
2868
3156
  })
2869
3157
  );
2870
3158
  }
@@ -3013,7 +3301,7 @@ function createMcpServer() {
3013
3301
  );
3014
3302
  server.tool(
3015
3303
  "siming_export",
3016
- "\u4ECE\u672C\u5730\u8D44\u4EA7\u6761\u76EE\u5BFC\u51FA\u5230 Siming server\uFF0C\u4E24\u9636\u6BB5\uFF1Aaction=plan \u751F\u6210\u8BA1\u5212\uFF08\u4E0D\u5199\u5165\uFF0C\u8FD4\u56DE created/updated/skipped/error \u5224\u5B9A\uFF09\uFF0Caction=apply \u6267\u884C\u8BA1\u5212\u3002entries \u4E3A JSON \u5B57\u7B26\u4E32\uFF0C\u9876\u5C42 {skipExisting?, skills?: [...], agents?: [...], dags?: [...]}\uFF08skipExisting \u7F3A\u7701 false\u2014\u2014server \u5DF2\u6709\u540C\u540D\u8D44\u4EA7\u65F6\u8DF3\u8FC7\uFF0C\u6761\u76EE\u7EA7\u53EF\u8986\u76D6\uFF09\u3002\u6761\u76EE\u5B57\u6BB5\u2014\u2014skill\uFF1A\u5FC5\u586B name\u3001content\uFF08SKILL \u6B63\u6587\uFF0C\u4E0D\u542B frontmatter\uFF09\uFF1B\u53EF\u9009 description\u3001category\uFF08\u7F3A\u7701 process\uFF09\u3001version\uFF08\u7F3A\u7701 1.0.0\uFF09\u3001scope\uFF08\u7F3A\u7701 global\uFF1Bproject \u987B projectKey\uFF09\u3002agent\uFF1A\u5FC5\u586B name\u3001systemPrompt\u3001model\uFF08\u987B\u4E3A\u5DF2\u6CE8\u518C model alias code\uFF09\uFF1B\u53EF\u9009 description\u3001boundSkills[]\u3001tools[]\u3001permissions[]\u3001version\u3001scope+projectKey\u3002dag\uFF1A\u5FC5\u586B projectKey\u3001nodes\u3001edges\uFF1B\u5176\u4F59\u5B57\u6BB5\u540C DAG \u6A21\u677F\u7ED3\u6784\uFF08name/description/edge pausePoint \u7B49\uFF09\u3002\u7248\u672C\u5224\u5B9A\uFF1Aserver \u65E0\u540C\u540D\u2192created\uFF1BskipExisting \u547D\u4E2D\u2192skipped\uFF1Bversion\u2260\u73B0\u503C\u2192updated\uFF1Bversion \u76F8\u540C\u2192\u5185\u5BB9\u8986\u76D6+\u672B\u4F4D patch+1\uFF08\u5185\u5BB9\u76F8\u540C\u4E0D\u9012\u589E\uFF09\u3002types \u8FC7\u6EE4\u6761\u76EE\u7C7B\u578B\uFF1Bonly \u6307\u5B9A\u5355\u6761\u91CD\u8BD5\u3002",
3304
+ "\u4ECE\u672C\u5730\u8D44\u4EA7\u6761\u76EE\u5BFC\u51FA\u5230 Siming server\uFF0C\u4E24\u9636\u6BB5\uFF1Aaction=plan \u751F\u6210\u8BA1\u5212\uFF08\u4E0D\u5199\u5165\uFF0C\u8FD4\u56DE created/updated/skipped/error \u5224\u5B9A\uFF09\uFF0Caction=apply \u6267\u884C\u8BA1\u5212\u3002entries \u4E3A JSON \u5B57\u7B26\u4E32\uFF0C\u9876\u5C42 {skipExisting?, skills?: [...], agents?: [...], dags?: [...]}\uFF08skipExisting \u7F3A\u7701 false\u2014\u2014server \u5DF2\u6709\u540C\u540D\u8D44\u4EA7\u65F6\u8DF3\u8FC7\uFF0C\u6761\u76EE\u7EA7\u53EF\u8986\u76D6\uFF09\u3002\u6761\u76EE\u5B57\u6BB5\u2014\u2014skill\uFF1A\u5FC5\u586B name\u3001content\uFF08SKILL \u6B63\u6587\uFF0C\u4E0D\u542B frontmatter\uFF09\uFF1B\u53EF\u9009 description\u3001category\uFF08\u7F3A\u7701 process\uFF09\u3001version\uFF08\u7F3A\u7701 1.0.0\uFF09\u3001scope\uFF08\u7F3A\u7701 global\uFF1Bproject \u987B projectKey\uFF09\u3001references\u3002agent\uFF1A\u5FC5\u586B name\u3001systemPrompt\u3001model\uFF08\u987B\u4E3A\u5DF2\u6CE8\u518C model alias code)\uFF1B\u53EF\u9009 description\u3001boundSkills[]\u3001tools[]\u3001permissions[]\u3001version\u3001scope+projectKey\u3001references\u3002references \u4E24\u6001\u8BED\u4E49\uFF08skill/agent \u540C\uFF09\uFF1A\u6761\u76EE\u7F3A references \u952E = \u4E0D\u4FEE\u6539 server \u73B0\u6709\u5F15\u7528\uFF08\u5355\u6587\u4EF6\u6761\u76EE\u4FDD\u6301\u7F3A\u7701\u5373\u96F6\u5F71\u54CD\uFF09\u3001\u663E\u5F0F [] = \u6E05\u7A7A\u5168\u90E8\u5F15\u7528\u3001\u975E\u7A7A\u6570\u7EC4 = \u6574\u7B14\u66FF\u6362\uFF1B\u5143\u7D20\u7ED3\u6784 [{path, content}]\uFF0Cpath \u4E3A\u76F8\u5BF9\u8D44\u4EA7\u6839\u7684\u6B63\u659C\u6760\u76F8\u5BF9\u8DEF\u5F84\uFF08\u7981\u7EDD\u5BF9\u8DEF\u5F84/../\u53CD\u659C\u6760/\u4E0E\u4E3B\u6587\u6863\u540D SKILL.md|agent.md \u51B2\u7A81/\u4E92\u4E3A\u76EE\u5F55\u524D\u7F00\uFF09\uFF0C\u4E0A\u9650\u5355\u8D44\u4EA7 20 \u6761\u3001\u5355\u6587\u6863 100 \u4E07\u5B57\u7B26\u3001\u4E3B\u6587\u6863+\u5F15\u7528\u603B\u91CF 300 \u4E07\u5B57\u7B26\u2014\u2014plan \u671F\u9884\u68C0\u975E\u6CD5\u6216\u8D85\u805A\u5408\u4E0A\u9650\u5373\u6807 error\uFF0C\u4E0D\u8FDB\u5165 apply\u3002dag\uFF1A\u5FC5\u586B projectKey\u3001nodes\u3001edges\uFF1B\u5176\u4F59\u5B57\u6BB5\u540C DAG \u6A21\u677F\u7ED3\u6784\uFF08name/description/edge pausePoint \u7B49\uFF09\u3002\u7248\u672C\u5224\u5B9A\uFF1Aserver \u65E0\u540C\u540D\u2192created\uFF1BskipExisting \u547D\u4E2D\u2192skipped\uFF1Bversion\u2260\u73B0\u503C\u2192updated\uFF1Bversion \u76F8\u540C\u2192\u5185\u5BB9\u8986\u76D6+\u672B\u4F4D patch+1\uFF08\u5185\u5BB9\u76F8\u540C\u4E0D\u9012\u589E\uFF09\u3002types \u8FC7\u6EE4\u6761\u76EE\u7C7B\u578B\uFF1Bonly \u6307\u5B9A\u5355\u6761\u91CD\u8BD5\u3002",
3017
3305
  exportArgs,
3018
3306
  async (args) => {
3019
3307
  let parsed;
@@ -3045,7 +3333,7 @@ function createMcpServer() {
3045
3333
  );
3046
3334
  server.tool(
3047
3335
  "siming_install",
3048
- "\u4ECE Siming server \u4E0B\u53D1\u8D44\u4EA7\u5230\u672C\u5730 .agents \u5F00\u653E\u534F\u8BAE\u901A\u7528\u843D\u70B9\uFF0C\u4E24\u9636\u6BB5\uFF1Aaction=plan \u751F\u6210\u5B89\u88C5\u8BA1\u5212\uFF08\u4E0D\u5199\u5165\uFF0C\u8FD4\u56DE install/update/skip/conflict \u5224\u5B9A\uFF09\uFF0Caction=apply \u6267\u884C\u5199\u5165\u3002scope=global \u5199\u5165 ~/.agents/\uFF08skills/\u3001agents/\u3001mcp.json\u2014\u2014MCP \u6CE8\u518C\u8FDB\u9876\u5C42 mcpServers.siming \u6761\u76EE\uFF0CSIMING_AGENTS_HOME \u53EF\u8986\u76D6\u6839\u76EE\u5F55\uFF09\uFF0Cscope=project \u5199\u5165\u5F53\u524D\u5DE5\u4F5C\u533A .agents/\uFF08\u9700\u5148\u7ED1\u5B9A\u9879\u76EE\uFF0C\u4E0D\u542B MCP \u6CE8\u518C\uFF09\u3002\u4E0D\u5199\u5165\u4EFB\u4F55\u7F16\u7A0B\u5DE5\u5177\u79C1\u6709\u76EE\u5F55\u3002force \u8986\u76D6\u6240\u6709\u9009\u4E2D\u7684\u672C\u5730\u8D44\u4EA7\uFF0C\u5305\u62EC\u76F8\u540C\u7248\u672C\u548C\u51B2\u7A81\u9879\uFF1Byes \u8DF3\u8FC7\u4EA4\u4E92\u786E\u8BA4\u3002apply \u8FD4\u56DE guidance \u8FC1\u79FB\u6307\u5F15\uFF08\u5168\u90E8\u8DF3\u8FC7\u7684\u5E42\u7B49\u91CD\u88C5\u540C\u6837\u8FD4\u56DE\uFF09\uFF0C\u4F9B\u5F53\u524D\u7F16\u7A0B\u5DE5\u5177\u4F1A\u8BDD\u4E2D\u7684 AI \u628A\u901A\u7528\u8D44\u4EA7\u6CE8\u518C\u5230\u672C\u5DE5\u5177\u81EA\u5DF1\u7684\u914D\u7F6E\u3002",
3336
+ "\u4ECE Siming server \u4E0B\u53D1\u8D44\u4EA7\u5230\u672C\u5730 .agents \u5F00\u653E\u534F\u8BAE\u901A\u7528\u843D\u70B9\uFF0C\u4E24\u9636\u6BB5\uFF1Aaction=plan \u751F\u6210\u5B89\u88C5\u8BA1\u5212\uFF08\u4E0D\u5199\u5165\uFF0C\u8FD4\u56DE install/update/skip/conflict \u5224\u5B9A\uFF09\uFF0Caction=apply \u6267\u884C\u5199\u5165\u3002scope=global \u5199\u5165 ~/.agents/\uFF08skills/\u3001agents/\u3001mcp.json\u2014\u2014MCP \u6CE8\u518C\u8FDB\u9876\u5C42 mcpServers.siming \u6761\u76EE\uFF0CSIMING_AGENTS_HOME \u53EF\u8986\u76D6\u6839\u76EE\u5F55\uFF09\uFF0Cscope=project \u5199\u5165\u5F53\u524D\u5DE5\u4F5C\u533A .agents/\uFF08\u9700\u5148\u7ED1\u5B9A\u9879\u76EE\uFF0C\u4E0D\u542B MCP \u6CE8\u518C\uFF09\u3002\u4E0D\u5199\u5165\u4EFB\u4F55\u7F16\u7A0B\u5DE5\u5177\u79C1\u6709\u76EE\u5F55\u3002force \u8986\u76D6\u6240\u6709\u9009\u4E2D\u7684\u672C\u5730\u8D44\u4EA7\uFF0C\u5305\u62EC\u76F8\u540C\u7248\u672C\u548C\u51B2\u7A81\u9879\uFF08\u4F8B\u5916\uFF1Aserver \u505C\u7528\u8D44\u4EA7\u6052 skip\u3001force \u4EA6\u4E0D\u843D\u76D8\uFF0C\u8BA1\u5212 reason \u6807\u6CE8 server asset disabled\uFF0C\u672C\u5730\u5DF2\u88C5\u6587\u4EF6\u4E0D\u53D7\u5F71\u54CD\u4E0D\u5220\u9664\uFF09\uFF1Byes \u8DF3\u8FC7\u4EA4\u4E92\u786E\u8BA4\u3002apply \u8FD4\u56DE guidance \u8FC1\u79FB\u6307\u5F15\uFF08\u5168\u90E8\u8DF3\u8FC7\u7684\u5E42\u7B49\u91CD\u88C5\u540C\u6837\u8FD4\u56DE\uFF09\uFF0C\u4F9B\u5F53\u524D\u7F16\u7A0B\u5DE5\u5177\u4F1A\u8BDD\u4E2D\u7684 AI \u628A\u901A\u7528\u8D44\u4EA7\u6CE8\u518C\u5230\u672C\u5DE5\u5177\u81EA\u5DF1\u7684\u914D\u7F6E\u3002",
3049
3337
  installArgs,
3050
3338
  async (args) => {
3051
3339
  const scope = args.scope ?? "global";
@@ -3156,13 +3444,17 @@ async function mcpServeCommand() {
3156
3444
 
3157
3445
  // src/commands/task/command.ts
3158
3446
  import { Command as Command5 } from "commander";
3159
- import { readFileSync as readFileSync7 } from "fs";
3447
+ import { readFileSync as readFileSync8 } from "fs";
3160
3448
  import { z as z5 } from "zod";
3161
- import { ARTIFACT_TYPES as ARTIFACT_TYPES2, TASK_TYPES as TASK_TYPES2 } from "@siming-org/core";
3449
+ import {
3450
+ ARTIFACT_TYPES as ARTIFACT_TYPES2,
3451
+ TASK_TYPES as TASK_TYPES2,
3452
+ ContextViewSchema
3453
+ } from "@siming-org/core";
3162
3454
  var PAGE_DEFAULT = 20;
3163
3455
  var PAGE_MAX = 500;
3164
3456
  function createTaskCommand() {
3165
- const task = new Command5("task").description("Task management \u2014 create, advance, approve, pause, resume, query");
3457
+ const task = new Command5("task").description("Task management \u2014 create, advance, approve, pause, resume, cancel, query");
3166
3458
  withCommonOpts(task.command("list"), "table").option("--status <s>", "filter by status").option("--track <t>", "filter by track").option("--project <key-or-id>", "filter by projectId (key or 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) => {
3167
3459
  const client = createClient(opts.url);
3168
3460
  const filters = {};
@@ -3319,9 +3611,18 @@ function createTaskCommand() {
3319
3611
  const result = await handleApprove(client, taskId, decisionR.data, opts.comment);
3320
3612
  renderResult(opts.format, result);
3321
3613
  });
3322
- withCommonOpts(task.command("context <taskId>"), "fancy").description("One-stop context for advancing: current node prompt, node states, pending pause edge, task doc background").action(async (taskId, opts) => {
3614
+ withCommonOpts(task.command("context <taskId>"), "fancy").description("One-stop context for advancing: current node prompt, node states, pending pause edge, task doc background").option("--view <v>", "basic\uFF08\u9ED8\u8BA4\uFF1A\u4E0D\u643A\u5E26 artifact \u5168\u6587\u5FEB\u7167\uFF09| full\uFF08\u65AD\u70B9\u7EED\u8DD1\u9700\u5386\u53F2\u4EA7\u7269\u5168\u6587\u65F6\u7528\uFF0C\u4E0E\u5168\u91CF\u5F62\u6001\u7B49\u4EF7\uFF09").action(async (taskId, opts) => {
3615
+ let view;
3616
+ if (opts.view !== void 0) {
3617
+ const viewR = parseEnum(opts.view, ContextViewSchema, "view");
3618
+ if (!viewR.success) {
3619
+ renderResult(opts.format, viewR);
3620
+ return;
3621
+ }
3622
+ view = viewR.data;
3623
+ }
3323
3624
  const client = createClient(opts.url);
3324
- const result = await handleGetContext(client, taskId);
3625
+ const result = await handleGetContext(client, taskId, view);
3325
3626
  renderResult(opts.format, result, { fields: result.success ? contextFields(result.data) : [] });
3326
3627
  });
3327
3628
  const doc = task.command("doc").description("Structured task doc \u2014 what/why/acceptance/non-goals (stored in siming DB)");
@@ -3352,7 +3653,7 @@ function createTaskCommand() {
3352
3653
  const client = createClient(opts.url);
3353
3654
  const result = await handleDocAcceptanceAdd(client, taskId, opts.text);
3354
3655
  if (result.success) {
3355
- renderResult(opts.format, result, { successMessage: `${taskId} acceptance \u5DF2\u6DFB\u52A0\uFF08\u5171 ${(result.data.doc?.acceptance ?? []).length} \u6761\uFF09` });
3656
+ renderResult(opts.format, result, { successMessage: `${taskId} acceptance \u5DF2\u6DFB\u52A0` });
3356
3657
  } else {
3357
3658
  renderResult(opts.format, result);
3358
3659
  }
@@ -3362,7 +3663,7 @@ function createTaskCommand() {
3362
3663
  const client = createClient(opts.url);
3363
3664
  const result = await handleDocNonGoalAdd(client, taskId, opts.text);
3364
3665
  if (result.success) {
3365
- renderResult(opts.format, result, { successMessage: `${taskId} non-goal \u5DF2\u6DFB\u52A0\uFF08\u5171 ${(result.data.doc?.nonGoals ?? []).length} \u6761\uFF09` });
3666
+ renderResult(opts.format, result, { successMessage: `${taskId} non-goal \u5DF2\u6DFB\u52A0` });
3366
3667
  } else {
3367
3668
  renderResult(opts.format, result);
3368
3669
  }
@@ -3377,6 +3678,11 @@ function createTaskCommand() {
3377
3678
  const result = await handleResume(client, taskId, opts.decision);
3378
3679
  renderResult("json", result);
3379
3680
  });
3681
+ task.command("cancel <taskId>").description("Cancel a task (active/paused \u2192 cancelled terminal state, irreversible)").option("--url <url>", "server base URL").option("--reason <text>", "cancel reason (1-500 chars)").action(async (taskId, opts) => {
3682
+ const client = createClient(opts.url);
3683
+ const result = await handleCancel(client, taskId, opts.reason);
3684
+ renderResult("json", result);
3685
+ });
3380
3686
  task.command("history <taskId>").description("Show task node history").option("--url <url>", "server base URL").option("--format <fmt>", "output format", "table").action(async (taskId, opts) => {
3381
3687
  const client = createClient(opts.url);
3382
3688
  const result = await handleGetHistory(client, taskId);
@@ -3408,9 +3714,7 @@ function createTaskCommand() {
3408
3714
  const client = createClient(opts.url);
3409
3715
  const result = await handleRecordCheckAdd(client, taskId, opts.node, opts.item, !opts.failed);
3410
3716
  if (result.success) {
3411
- const checks = (result.data.nodeRecords ?? {})[opts.node]?.checks ?? [];
3412
- const last = checks[checks.length - 1];
3413
- renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} check \u5DF2\u6DFB\u52A0\uFF08\u5171 ${checks.length} \u6761\uFF0C\u65B0\u6761\u76EE id ${last?.id ?? "?"}\uFF09` });
3717
+ renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} check \u5DF2\u6DFB\u52A0\uFF08\u65B0\u6761\u76EE id ${result.data.entry?.id ?? "?"}\uFF09` });
3414
3718
  } else {
3415
3719
  renderResult(opts.format, result);
3416
3720
  }
@@ -3443,7 +3747,7 @@ function createTaskCommand() {
3443
3747
  let content;
3444
3748
  if (opts.file) {
3445
3749
  try {
3446
- content = readFileSync7(opts.file, "utf-8");
3750
+ content = readFileSync8(opts.file, "utf-8");
3447
3751
  } catch (e) {
3448
3752
  renderResult(opts.format, fail({ message: `\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25: ${opts.file}\uFF08${e instanceof Error ? e.message : String(e)}\uFF09`, httpStatus: 0 }));
3449
3753
  return;
@@ -3457,8 +3761,7 @@ function createTaskCommand() {
3457
3761
  const client = createClient(opts.url);
3458
3762
  const result = await handleRecordArtifactAdd(client, taskId, opts.node, typeR.data, path, opts.note, content);
3459
3763
  if (result.success) {
3460
- const artifacts = (result.data.nodeRecords ?? {})[opts.node]?.artifacts ?? [];
3461
- renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} artifact \u5DF2\u6DFB\u52A0\uFF08\u5171 ${artifacts.length} \u6761\uFF1A${typeR.data} ${path}${content !== void 0 ? "\uFF08\u542B\u5168\u6587\u5FEB\u7167 " + content.length + " \u5B57\u7B26\uFF09" : ""}\uFF09` });
3764
+ renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} artifact \u5DF2\u6DFB\u52A0\uFF08\u65B0\u6761\u76EE id ${result.data.entry?.id ?? "?"}\uFF1A${typeR.data} ${path}${content !== void 0 ? "\uFF08\u542B\u5168\u6587\u5FEB\u7167 " + content.length + " \u5B57\u7B26\uFF09" : ""}\uFF09` });
3462
3765
  } else {
3463
3766
  renderResult(opts.format, result);
3464
3767
  }
@@ -3467,8 +3770,7 @@ function createTaskCommand() {
3467
3770
  const client = createClient(opts.url);
3468
3771
  const result = await handleRecordConfirmAdd(client, taskId, opts.node, opts.quote);
3469
3772
  if (result.success) {
3470
- const confirmations = (result.data.nodeRecords ?? {})[opts.node]?.confirmations ?? [];
3471
- renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} \u786E\u8BA4\u539F\u6587\u5DF2\u8BB0\u5F55\uFF08\u5171 ${confirmations.length} \u6761\uFF09` });
3773
+ renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} \u786E\u8BA4\u539F\u6587\u5DF2\u8BB0\u5F55\uFF08\u65B0\u6761\u76EE id ${result.data.entry?.id ?? "?"}\uFF09` });
3472
3774
  } else {
3473
3775
  renderResult(opts.format, result);
3474
3776
  }
@@ -3478,8 +3780,7 @@ function createTaskCommand() {
3478
3780
  const client = createClient(opts.url);
3479
3781
  const result = await handleRecordDecisionAdd(client, taskId, opts.node, opts.topic, opts.decision);
3480
3782
  if (result.success) {
3481
- const decisions = (result.data.nodeRecords ?? {})[opts.node]?.decisions ?? [];
3482
- renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} \u51B3\u7B56\u5DF2\u8BB0\u5F55\uFF08\u5171 ${decisions.length} \u6761\uFF1A${opts.topic}\uFF09` });
3783
+ renderResult(opts.format, result, { successMessage: `${taskId} \u8282\u70B9 ${opts.node} \u51B3\u7B56\u5DF2\u8BB0\u5F55\uFF08\u65B0\u6761\u76EE id ${result.data.entry?.id ?? "?"}\uFF1A${opts.topic}\uFF09` });
3483
3784
  } else {
3484
3785
  renderResult(opts.format, result);
3485
3786
  }
@@ -3518,7 +3819,7 @@ function createTaskCommand() {
3518
3819
  const client = createClient(opts.url);
3519
3820
  const result = await handleArchNoteAdd(client, taskId, opts.text);
3520
3821
  if (result.success) {
3521
- renderResult(opts.format, result, { successMessage: `${taskId} \u7D2F\u79EF\u7D20\u6750\u5DF2\u6DFB\u52A0\uFF08\u5171 ${(result.data.archNotes ?? []).length} \u6761\uFF09` });
3822
+ renderResult(opts.format, result, { successMessage: `${taskId} \u7D2F\u79EF\u7D20\u6750\u5DF2\u6DFB\u52A0\uFF08\u65B0\u6761\u76EE id ${result.data.entry?.id ?? "?"}\uFF09` });
3522
3823
  } else {
3523
3824
  renderResult(opts.format, result);
3524
3825
  }
@@ -3629,7 +3930,7 @@ function progressText(row) {
3629
3930
 
3630
3931
  // src/commands/skill/command.ts
3631
3932
  import { Command as Command6 } from "commander";
3632
- import { SkillScopeSchema as SkillScopeSchema2 } from "@siming-org/core";
3933
+ import { SKILL_MAIN_DOC as SKILL_MAIN_DOC4, SkillScopeSchema as SkillScopeSchema2 } from "@siming-org/core";
3633
3934
  function createSkillCommand() {
3634
3935
  const skill = new Command6("skill").description("Skill management \u2014 global/project-scoped skills");
3635
3936
  withCommonOpts(skill.command("list"), "table").option("--project <id>", "filter by projectId").description("List skills").action(async (opts) => {
@@ -3641,6 +3942,7 @@ function createSkillCommand() {
3641
3942
  { key: "category", header: "Category" },
3642
3943
  { key: "scope", header: "Scope" },
3643
3944
  { key: "version", header: "Version" },
3945
+ { key: "referenceCount", header: "Refs" },
3644
3946
  { key: "description", header: "Description", maxWidth: 40 }
3645
3947
  ]
3646
3948
  });
@@ -3650,7 +3952,7 @@ function createSkillCommand() {
3650
3952
  const result = await handleGetSkill(client, name);
3651
3953
  renderResult(opts.format, result, { fields: result.success ? skillFields(result.data) : [] });
3652
3954
  });
3653
- 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("--project-id <hex>", "projectId (required when scope=project)").action(async (opts) => {
3955
+ 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 <hex>", "projectId (required when scope=project)").action(async (opts) => {
3654
3956
  const categoryR = parseEnum(opts.category, SkillCategorySchema, "category");
3655
3957
  if (!categoryR.success) {
3656
3958
  renderResult("json", categoryR);
@@ -3661,6 +3963,11 @@ function createSkillCommand() {
3661
3963
  renderResult("json", scopeR);
3662
3964
  return;
3663
3965
  }
3966
+ const refsR = parseRefFlags(opts.ref ?? [], SKILL_MAIN_DOC4);
3967
+ if (!refsR.success) {
3968
+ renderResult("json", refsR);
3969
+ return;
3970
+ }
3664
3971
  const client = createClient(opts.url);
3665
3972
  const input = {
3666
3973
  name: opts.name,
@@ -3669,12 +3976,13 @@ function createSkillCommand() {
3669
3976
  category: categoryR.data,
3670
3977
  scope: scopeR.data,
3671
3978
  version: "1.0.0",
3979
+ ...refsR.data.length > 0 ? { references: refsR.data } : {},
3672
3980
  ...opts.projectId ? { projectId: opts.projectId } : {}
3673
3981
  };
3674
3982
  const result = await handleCreateSkill(client, input);
3675
3983
  renderResult("json", result);
3676
3984
  });
3677
- skill.command("update <name>").description("Update a skill (partial)").option("--url <url>", "server base URL").option("--description <text>", "new description").option("--content <text>", "new content").option("--version <v>", "new version").option("--scope <scope>", "global|project").option("--project-id <hex>", "projectId").action(async (name, opts) => {
3985
+ 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("--version <v>", "new version").option("--scope <scope>", "global|project").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 <hex>", "projectId").action(async (name, opts) => {
3678
3986
  const client = createClient(opts.url);
3679
3987
  let scope;
3680
3988
  if (opts.scope !== void 0) {
@@ -3685,11 +3993,31 @@ function createSkillCommand() {
3685
3993
  }
3686
3994
  scope = scopeR.data;
3687
3995
  }
3996
+ let references;
3997
+ if (opts.clearRefs === true && (opts.ref ?? []).length > 0) {
3998
+ renderResult("json", fail({
3999
+ message: "--clear-refs \u4E0E --ref \u4E92\u65A5\uFF0C\u4E8C\u9009\u4E00",
4000
+ httpStatus: 0,
4001
+ hint: "\u6E05\u7A7A\u5F15\u7528\u7528 --clear-refs\uFF1B\u66FF\u6362\u5F15\u7528\u7528 --ref path@file\uFF08\u53EF\u91CD\u590D\uFF09"
4002
+ }));
4003
+ return;
4004
+ }
4005
+ if (opts.clearRefs === true) {
4006
+ references = [];
4007
+ } else if ((opts.ref ?? []).length > 0) {
4008
+ const refsR = parseRefFlags(opts.ref ?? [], SKILL_MAIN_DOC4);
4009
+ if (!refsR.success) {
4010
+ renderResult("json", refsR);
4011
+ return;
4012
+ }
4013
+ references = refsR.data;
4014
+ }
3688
4015
  const patch = {
3689
4016
  ...opts.description !== void 0 ? { description: opts.description } : {},
3690
4017
  ...opts.content !== void 0 ? { content: opts.content } : {},
3691
4018
  ...opts.version !== void 0 ? { version: opts.version } : {},
3692
4019
  ...scope !== void 0 ? { scope } : {},
4020
+ ...references !== void 0 ? { references } : {},
3693
4021
  ...opts.projectId !== void 0 ? { projectId: opts.projectId } : {}
3694
4022
  };
3695
4023
  const result = await handleUpdateSkill(client, name, patch);
@@ -3724,13 +4052,15 @@ function skillFields(s) {
3724
4052
  ["projectId", s.projectId],
3725
4053
  ["version", s.version],
3726
4054
  ["description", s.description],
3727
- ["content", s.content.length > 200 ? s.content.slice(0, 200) + "\u2026" : s.content]
4055
+ ["content", s.content.length > 200 ? s.content.slice(0, 200) + "\u2026" : s.content],
4056
+ // T202608270002:引用文档清单(path 列表;无引用时不显示该行)
4057
+ ...s.references?.length ? [["references", s.references.map((r) => r.path).join(", ")]] : []
3728
4058
  ];
3729
4059
  }
3730
4060
 
3731
4061
  // src/commands/agent/command.ts
3732
4062
  import { Command as Command7 } from "commander";
3733
- import { AgentScopeSchema as AgentScopeSchema2 } from "@siming-org/core";
4063
+ import { AGENT_MAIN_DOC as AGENT_MAIN_DOC4, AgentScopeSchema as AgentScopeSchema2, AgentFunctionSchema as AgentFunctionSchema2 } from "@siming-org/core";
3734
4064
  function createAgentCommand() {
3735
4065
  const agent = new Command7("agent").description("Agent management \u2014 subagent definitions (global/project scope)");
3736
4066
  withCommonOpts(agent.command("list"), "table").option("--project <id>", "filter by projectId").description("List agents").action(async (opts) => {
@@ -3741,7 +4071,9 @@ function createAgentCommand() {
3741
4071
  { key: "name", header: "Name" },
3742
4072
  { key: "model", header: "Model" },
3743
4073
  { key: "scope", header: "Scope" },
4074
+ { key: "function", header: "Function" },
3744
4075
  { key: "boundSkills", header: "Bound Skills", maxWidth: 30 },
4076
+ { key: "referenceCount", header: "Refs" },
3745
4077
  { key: "description", header: "Description", maxWidth: 40 }
3746
4078
  ]
3747
4079
  });
@@ -3751,12 +4083,26 @@ function createAgentCommand() {
3751
4083
  const result = await handleGetAgent(client, name);
3752
4084
  renderResult(opts.format, result, { fields: result.success ? agentFields(result.data) : [] });
3753
4085
  });
3754
- 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("--bound-skill <name>", "bound skill name (repeatable)", collectArgs, []).option("--tool <name>", "tool name (repeatable)", collectArgs, []).option("--permission <name>", "permission name (repeatable)", collectArgs, []).option("--project-id <hex>", "projectId (required when scope=project)").action(async (opts) => {
4086
+ 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 <hex>", "projectId (required when scope=project)").action(async (opts) => {
3755
4087
  const scopeR = parseEnum(opts.scope, AgentScopeSchema2, "scope");
3756
4088
  if (!scopeR.success) {
3757
4089
  renderResult("json", scopeR);
3758
4090
  return;
3759
4091
  }
4092
+ let agentFunction;
4093
+ if (opts.function !== void 0) {
4094
+ const fnR = parseEnum(opts.function, AgentFunctionSchema2, "function");
4095
+ if (!fnR.success) {
4096
+ renderResult("json", fnR);
4097
+ return;
4098
+ }
4099
+ agentFunction = fnR.data;
4100
+ }
4101
+ const refsR = parseRefFlags(opts.ref ?? [], AGENT_MAIN_DOC4);
4102
+ if (!refsR.success) {
4103
+ renderResult("json", refsR);
4104
+ return;
4105
+ }
3760
4106
  const client = createClient(opts.url);
3761
4107
  const input = {
3762
4108
  name: opts.name,
@@ -3765,15 +4111,18 @@ function createAgentCommand() {
3765
4111
  model: opts.model,
3766
4112
  version: "1.0.0",
3767
4113
  scope: scopeR.data,
4114
+ // AgentCreate 输出类型 function 必有:显式缺省 executor(与 API 缺省归一一致)
4115
+ "function": agentFunction ?? "executor",
3768
4116
  boundSkills: opts.boundSkill,
3769
4117
  tools: opts.tool,
3770
4118
  permissions: opts.permission,
4119
+ ...refsR.data.length > 0 ? { references: refsR.data } : {},
3771
4120
  ...opts.projectId ? { projectId: opts.projectId } : {}
3772
4121
  };
3773
4122
  const result = await handleCreateAgent(client, input);
3774
4123
  renderResult("json", result);
3775
4124
  });
3776
- 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").option("--bound-skill <name>", "replace bound skills (repeatable)", collectArgs, []).option("--tool <name>", "replace tools (repeatable)", collectArgs, []).option("--permission <name>", "replace permissions (repeatable)", collectArgs, []).option("--project-id <hex>", "projectId").action(async (name, opts) => {
4125
+ 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").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 <hex>", "projectId").action(async (name, opts) => {
3777
4126
  const client = createClient(opts.url);
3778
4127
  let scope;
3779
4128
  if (opts.scope !== void 0) {
@@ -3784,14 +4133,44 @@ function createAgentCommand() {
3784
4133
  }
3785
4134
  scope = scopeR.data;
3786
4135
  }
4136
+ let agentFunction;
4137
+ if (opts.function !== void 0) {
4138
+ const fnR = parseEnum(opts.function, AgentFunctionSchema2, "function");
4139
+ if (!fnR.success) {
4140
+ renderResult("json", fnR);
4141
+ return;
4142
+ }
4143
+ agentFunction = fnR.data;
4144
+ }
4145
+ let references;
4146
+ if (opts.clearRefs === true && opts.ref.length > 0) {
4147
+ renderResult("json", fail({
4148
+ message: "--clear-refs \u4E0E --ref \u4E92\u65A5\uFF0C\u4E8C\u9009\u4E00",
4149
+ httpStatus: 0,
4150
+ hint: "\u6E05\u7A7A\u5F15\u7528\u7528 --clear-refs\uFF1B\u66FF\u6362\u5F15\u7528\u7528 --ref path@file\uFF08\u53EF\u91CD\u590D\uFF09"
4151
+ }));
4152
+ return;
4153
+ }
4154
+ if (opts.clearRefs === true) {
4155
+ references = [];
4156
+ } else if (opts.ref.length > 0) {
4157
+ const refsR = parseRefFlags(opts.ref, AGENT_MAIN_DOC4);
4158
+ if (!refsR.success) {
4159
+ renderResult("json", refsR);
4160
+ return;
4161
+ }
4162
+ references = refsR.data;
4163
+ }
3787
4164
  const patch = {
3788
4165
  ...opts.description !== void 0 ? { description: opts.description } : {},
3789
4166
  ...opts.systemPrompt !== void 0 ? { systemPrompt: opts.systemPrompt } : {},
3790
4167
  ...opts.model !== void 0 ? { model: opts.model } : {},
3791
4168
  ...scope !== void 0 ? { scope } : {},
4169
+ ...agentFunction !== void 0 ? { "function": agentFunction } : {},
3792
4170
  ...opts.boundSkill.length > 0 ? { boundSkills: opts.boundSkill } : {},
3793
4171
  ...opts.tool.length > 0 ? { tools: opts.tool } : {},
3794
4172
  ...opts.permission.length > 0 ? { permissions: opts.permission } : {},
4173
+ ...references !== void 0 ? { references } : {},
3795
4174
  ...opts.projectId !== void 0 ? { projectId: opts.projectId } : {}
3796
4175
  };
3797
4176
  const result = await handleUpdateAgent(client, name, patch);
@@ -3823,16 +4202,20 @@ function agentFields(a) {
3823
4202
  ["name", a.name],
3824
4203
  ["model", a.model],
3825
4204
  ["scope", a.scope],
4205
+ ["function", a["function"]],
3826
4206
  ["projectId", a.projectId],
3827
4207
  ["boundSkills", a.boundSkills],
3828
4208
  ["tools", a.tools],
3829
4209
  ["permissions", a.permissions],
4210
+ // T202608270002:引用文档清单(path 列表;无引用时不显示该行)
4211
+ ...a.references?.length ? [["references", a.references.map((r) => r.path).join(", ")]] : [],
3830
4212
  ["description", a.description],
3831
4213
  ["systemPrompt", a.systemPrompt]
3832
4214
  ];
3833
4215
  }
3834
4216
 
3835
4217
  // src/commands/dag/command.ts
4218
+ import { readFileSync as readFileSync9 } from "fs";
3836
4219
  import { Command as Command8 } from "commander";
3837
4220
  function createDagCommand() {
3838
4221
  const dag = new Command8("dag").description("DAG template & instance management");
@@ -3866,13 +4249,26 @@ function createDagCommand() {
3866
4249
  const result = await handleGetTemplate(client, templateId);
3867
4250
  renderResult(opts.format, result, { fields: result.success ? templateFields(result.data) : [] });
3868
4251
  });
3869
- tpl.command("import <file>").description("Import template from YAML (DagTemplateCreateSchema \u7684 YAML \u8868\u793A)").option("--url <url>", "server base URL").option("--project <id>", "override projectId (defaults to YAML projectId)").option("--name <name>", "override template name").action(async (file, opts) => {
4252
+ tpl.command("import <file>").description(
4253
+ "Import a DAG template from file \u2014 bundle JSON (with dependency closure, plan\u2192apply) or YAML single template (format auto-detected by content)"
4254
+ ).option("--url <url>", "server base URL").option("--project <key|id>", "target project (key or id); YAML channel: overrides projectId, bundle channel: import target").option("--name <name>", "override template name (YAML channel only)").option("--overwrite-deps", "bundle channel: force-overwrite conflicting dependencies").option("--plan", "bundle channel: preview only (plan without apply)").action(async (file, opts) => {
3870
4255
  const client = createClient(opts.url);
3871
- const result = await handleImportTemplate(client, file, {
3872
- ...opts.project ? { projectId: opts.project } : {},
3873
- ...opts.name ? { name: opts.name } : {}
3874
- });
3875
- renderResult("json", result);
4256
+ let text;
4257
+ try {
4258
+ text = readFileSync9(file, "utf-8");
4259
+ } catch (e) {
4260
+ renderResult("json", fail({
4261
+ message: `\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25: ${file}\uFF08${e instanceof Error ? e.message : String(e)}\uFF09`,
4262
+ httpStatus: 0,
4263
+ hint: "\u786E\u8BA4\u8DEF\u5F84\u5B58\u5728\u4E14\u53EF\u8BFB\uFF1Bnpm \u5168\u5C40\u5B89\u88C5\u7684\u5185\u7F6E\u6A21\u677F\u4F4D\u4E8E <\u5B89\u88C5\u76EE\u5F55>/node_modules/@siming-org/cli/templates/builtin/"
4264
+ }));
4265
+ return;
4266
+ }
4267
+ if (isBundleText(text)) {
4268
+ await runBundleImport(client, text, opts);
4269
+ return;
4270
+ }
4271
+ await runYamlImport(client, text, opts, jsonParseError(text));
3876
4272
  });
3877
4273
  const inst = dag.command("instance").description("Task DAG instance");
3878
4274
  withCommonOpts(inst.command("show <taskId>"), "fancy").description("Show task DAG instance").action(async (taskId, opts) => {
@@ -3919,6 +4315,146 @@ function pausePointsText(row) {
3919
4315
  if (!Array.isArray(pp) || pp.length === 0) return "\u2014";
3920
4316
  return pp.join(", ");
3921
4317
  }
4318
+ function isBundleText(text) {
4319
+ try {
4320
+ const parsed = JSON.parse(text);
4321
+ return typeof parsed === "object" && parsed !== null && "exportFormatVersion" in parsed;
4322
+ } catch {
4323
+ return false;
4324
+ }
4325
+ }
4326
+ function jsonParseError(text) {
4327
+ try {
4328
+ JSON.parse(text);
4329
+ return void 0;
4330
+ } catch (e) {
4331
+ return e instanceof Error ? e.message : String(e);
4332
+ }
4333
+ }
4334
+ async function runYamlImport(client, yamlText, opts, jsonParseError2) {
4335
+ if (opts.plan === true || opts.overwriteDeps === true) {
4336
+ renderResult("json", fail({
4337
+ message: "--plan / --overwrite-deps \u4EC5\u5BF9 bundle \u6587\u4EF6\u751F\u6548\uFF08\u5F53\u524D\u6587\u4EF6\u8BC6\u522B\u4E3A YAML \u5355\u6A21\u677F\uFF09",
4338
+ httpStatus: 0,
4339
+ hint: "bundle \u662F export \u7AEF\u70B9\u4EA7\u7269\uFF08JSON \u542B exportFormatVersion \u4E0E\u4F9D\u8D56\u95ED\u5305\uFF09\uFF1BYAML \u5355\u6A21\u677F\u5BFC\u5165\u65E0\u51B2\u7A81\u51B3\u7B56\u73AF\u8282"
4340
+ }));
4341
+ return;
4342
+ }
4343
+ let projectId;
4344
+ if (opts.project !== void 0) {
4345
+ const r = await resolveProjectId(client, opts.project);
4346
+ if (!r.success) {
4347
+ renderResult("json", r);
4348
+ return;
4349
+ }
4350
+ projectId = r.data;
4351
+ }
4352
+ const result = await importTemplateFromYaml(client, yamlText, {
4353
+ ...projectId !== void 0 ? { projectId } : {},
4354
+ ...opts.name !== void 0 ? { name: opts.name } : {}
4355
+ });
4356
+ if (!result.success && jsonParseError2 !== void 0 && result.error.bizCode === "YAML_PARSE_FAILED") {
4357
+ renderResult("json", fail({
4358
+ message: `\u6587\u4EF6\u65E2\u975E bundle \u4E5F\u975E\u6A21\u677F YAML\uFF1A
4359
+ JSON \u89E3\u6790: ${jsonParseError2}
4360
+ YAML \u89E3\u6790: ${result.error.message}`,
4361
+ httpStatus: 0,
4362
+ hint: "bundle \u662F export \u7AEF\u70B9\u4EA7\u7269\uFF08JSON \u9876\u5C42\u542B exportFormatVersion\uFF09\uFF1B\u6A21\u677F YAML \u987B\u7B26\u5408 DagTemplateCreateSchema\uFF08\u89C1 CLI \u4F7F\u7528\u624B\u518C \xA714\uFF09"
4363
+ }));
4364
+ return;
4365
+ }
4366
+ renderResult("json", result);
4367
+ }
4368
+ async function runBundleImport(client, bundleText, opts) {
4369
+ if (opts.name !== void 0) {
4370
+ renderResult("json", fail({
4371
+ message: "--name \u4EC5\u5BF9 YAML \u6A21\u677F\u751F\u6548\uFF08bundle \u6A21\u677F\u540D\u4EE5\u5BFC\u51FA\u5FEB\u7167\u4E3A\u51C6\uFF0C\u547D\u4EE4\u5C42\u4E0D\u91CD\u547D\u540D\uFF09",
4372
+ httpStatus: 0,
4373
+ hint: "\u5BFC\u5165\u540E\u53EF\u5728 Web \u7BA1\u7406\u53F0\u7F16\u8F91\u6A21\u677F\u4FE1\u606F\uFF1B\u81EA\u5B9A\u4E49\u540D\u8BF7\u8D70 YAML \u901A\u9053"
4374
+ }));
4375
+ return;
4376
+ }
4377
+ const target = await resolveImportTargetProject(client, opts.project);
4378
+ if (!target.success) {
4379
+ renderResult("json", target);
4380
+ return;
4381
+ }
4382
+ const result = await importTemplateBundle(client, bundleText, {
4383
+ targetProjectId: target.data,
4384
+ ...opts.overwriteDeps === true ? { overwriteDeps: true } : {},
4385
+ ...opts.plan === true ? { planOnly: true } : {}
4386
+ });
4387
+ if (!result.success) {
4388
+ renderResult("json", result);
4389
+ return;
4390
+ }
4391
+ renderBundleImportOutcome(result.data, opts.plan === true);
4392
+ }
4393
+ async function resolveImportTargetProject(client, projectOpt) {
4394
+ if (projectOpt !== void 0) return resolveProjectId(client, projectOpt);
4395
+ const wsDefault = readWorkspaceConfig()?.defaultProject;
4396
+ if (wsDefault !== void 0) {
4397
+ const r = await resolveProjectId(client, wsDefault);
4398
+ if (!r.success) {
4399
+ return fail({
4400
+ ...r.error,
4401
+ hint: `workspace defaultProject "${wsDefault}" \u89E3\u6790\u5931\u8D25\u2014\u2014siming config unset defaultProject \u540E\u91CD\u8BD5\uFF0C\u6216\u663E\u5F0F --project <key|id>`
4402
+ });
4403
+ }
4404
+ return r;
4405
+ }
4406
+ const list = await handleListProjects(client);
4407
+ if (!list.success) return list;
4408
+ const defaultProject = list.data.find((p) => p.key === "default");
4409
+ if (defaultProject?.id === void 0) {
4410
+ return fail({
4411
+ 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",
4412
+ httpStatus: 0,
4413
+ hint: "pass --project <key|id>\uFF0C\u6216\u5148 siming project create + siming init --project <key>"
4414
+ });
4415
+ }
4416
+ return { success: true, data: defaultProject.id };
4417
+ }
4418
+ function renderBundleImportOutcome(outcome, planOnly) {
4419
+ const t = outcome.plan.template;
4420
+ const overwritten = t.willOverwrite && t.currentVersion !== void 0 ? `\u8986\u76D6\u73B0\u6709 v${t.currentVersion} \u2192 ` : "";
4421
+ console.log(`\u6A21\u677F ${t.name}: ${overwritten}v${t.importVersion}`);
4422
+ if (!t.isDefaultEffect) {
4423
+ console.log(` \u9ED8\u8BA4\u6A21\u677F: \u751F\u6548 false${t.downgradeReason !== void 0 ? `\uFF08${t.downgradeReason}\uFF09` : ""}`);
4424
+ }
4425
+ const byStatus = countBy(outcome.plan.dependencies, (d) => d.status);
4426
+ console.log(
4427
+ `\u4F9D\u8D56\u9884\u68C0: create ${byStatus.create ?? 0} / identical ${byStatus.identical ?? 0} / conflict ${byStatus.conflict ?? 0}`
4428
+ );
4429
+ for (const d of outcome.plan.dependencies) {
4430
+ if (d.status !== "conflict") continue;
4431
+ const scope = d.scope !== void 0 ? `(${d.scope})` : "";
4432
+ const versions = d.currentVersion !== void 0 ? ` v${d.currentVersion} \u2192 v${d.importVersion ?? "?"}` : "";
4433
+ const diff = d.changeSummary !== void 0 ? ` \u5DEE\u5F02: ${d.changeSummary}` : "";
4434
+ console.log(` conflict [${d.kind}] ${d.name}${scope}${versions}${diff}`);
4435
+ }
4436
+ for (const w of outcome.plan.warnings) console.log(` \u8B66\u544A: ${w}`);
4437
+ if (outcome.apply === void 0) {
4438
+ console.log(planOnly ? "\u2500\u2500 \u4EC5\u9884\u68C0\uFF08--plan\uFF09\uFF0C\u672A\u6267\u884C\u5BFC\u5165 \u2500\u2500" : "\u2500\u2500 \u672A\u6267\u884C\u5BFC\u5165 \u2500\u2500");
4439
+ return;
4440
+ }
4441
+ const byAction = countBy(outcome.apply.dependencies, (d) => d.action);
4442
+ console.log(
4443
+ `\u5BFC\u5165\u5B8C\u6210: \u6A21\u677F ${outcome.apply.template.action}\uFF08id ${outcome.apply.template.id}\uFF09\uFF1B\u4F9D\u8D56 created ${byAction.created ?? 0} / updated ${byAction.updated ?? 0} / skipped ${byAction.skipped ?? 0} / identical ${byAction.identical ?? 0} / failed ${byAction.failed ?? 0}`
4444
+ );
4445
+ for (const d of outcome.apply.dependencies) {
4446
+ if (d.action !== "failed") continue;
4447
+ console.log(` failed [${d.kind}] ${d.name}${d.message !== void 0 ? `: ${d.message}` : ""}`);
4448
+ }
4449
+ }
4450
+ function countBy(items, keyOf) {
4451
+ const counts = {};
4452
+ for (const item of items) {
4453
+ const k = keyOf(item);
4454
+ counts[k] = (counts[k] ?? 0) + 1;
4455
+ }
4456
+ return counts;
4457
+ }
3922
4458
 
3923
4459
  // src/commands/sync/command.ts
3924
4460
  import { Command as Command9 } from "commander";
@@ -4061,7 +4597,7 @@ function createConfigCommand() {
4061
4597
 
4062
4598
  // src/commands/export/command.ts
4063
4599
  import { Command as Command12 } from "commander";
4064
- import { readFileSync as readFileSync8 } from "fs";
4600
+ import { readFileSync as readFileSync10 } from "fs";
4065
4601
  import { parse as parseYaml3 } from "yaml";
4066
4602
  function createExportCommand() {
4067
4603
  const exportCmd = new Command12("export").description("Export local assets (skills/agents/dags) to Siming \u2014 plan then apply");
@@ -4106,7 +4642,7 @@ function createExportCommand() {
4106
4642
  async function runExportPlan(client, filePath, typesArg) {
4107
4643
  let raw;
4108
4644
  try {
4109
- const text = readFileSync8(filePath, "utf-8");
4645
+ const text = readFileSync10(filePath, "utf-8");
4110
4646
  raw = parseYaml3(text);
4111
4647
  } catch (e) {
4112
4648
  return fail({
@@ -4131,7 +4667,7 @@ async function runExportPlan(client, filePath, typesArg) {
4131
4667
  }
4132
4668
  function loadPlanFile(path) {
4133
4669
  try {
4134
- const text = readFileSync8(path, "utf-8");
4670
+ const text = readFileSync10(path, "utf-8");
4135
4671
  const parsed = JSON.parse(text);
4136
4672
  if (!Array.isArray(parsed.items)) {
4137
4673
  return fail({ message: `\u8BA1\u5212\u6587\u4EF6\u7ED3\u6784\u65E0\u6548\uFF1A\u7F3A\u5C11 items \u6570\u7EC4`, httpStatus: 0, hint: "\u8BA1\u5212\u6587\u4EF6\u7531 `siming export plan --format json > plan.json` \u751F\u6210" });
@@ -4192,11 +4728,121 @@ function renderReport(report, format) {
4192
4728
  }
4193
4729
  }
4194
4730
 
4195
- // src/commands/settings/command.ts
4731
+ // src/commands/guide.ts
4196
4732
  import { Command as Command13 } from "commander";
4733
+
4734
+ // src/commands/guide-content.ts
4735
+ var GUIDE_TEXT = `================================================================
4736
+ \u65B0\u9879\u76EE\u63A5\u5165 siming \u5F00\u53D1\u6D41\u7A0B\u6307\u5BFC
4737
+ ================================================================
4738
+
4739
+ \u672C\u6307\u5BFC\u9762\u5411\u9996\u6B21\u5C06\u9879\u76EE\u63A5\u5165 siming \u5F00\u53D1\u6D41\u7A0B\u7684\u6280\u672F\u8D1F\u8D23\u4EBA\u4E0E AI \u7F16\u7A0B\u4EE3\u7406\uFF0C
4740
+ \u8986\u76D6\u56DB\u6B65\uFF1A\u8865\u9F50\u9879\u76EE\u58F0\u660E \u2192 \u914D\u7F6E\u6D41\u7A0B\u6A21\u677F \u2192 \u5EFA\u7ACB\u9879\u76EE\u7EA7\u8D44\u4EA7 \u2192 \u9A8C\u8BC1\u63A5\u5165\u3002
4741
+
4742
+ ----------------------------------------------------------------
4743
+ \u4E00\u3001\u9879\u76EE AGENTS.md \u5FC5\u5907\u58F0\u660E checklist
4744
+ ----------------------------------------------------------------
4745
+
4746
+ \u6D41\u7A0B\u6A21\u677F\u7684\u8282\u70B9\u63D0\u793A\u8BCD\u4E2D\uFF0C\u73AF\u5883\u76F8\u5173\u4FE1\u606F\u5168\u90E8\u53C2\u6570\u5316\u4E3A\u300C\u6309\u9879\u76EE\u58F0\u660E\u300D\uFF0C
4747
+ \u58F0\u660E\u503C\u843D\u70B9 = \u9879\u76EE\u4ED3\u5E93\u7684 AI \u5165\u53E3\u6587\u4EF6\uFF08\u9879\u76EE AGENTS.md\uFF09\u3002
4748
+ \u4EE5\u4E0B 8 \u9879\u58F0\u660E\u4E0D\u9F50\u65F6\uFF0C\u6D41\u7A0B\u4F1A\u5728\u5BF9\u5E94\u73AF\u8282\u6682\u505C\u8BE2\u95EE\u6216\u964D\u7EA7\uFF1A
4749
+
4750
+ | # | \u58F0\u660E\u9879 | \u58F0\u660E\u5185\u5BB9 | \u7F3A\u5931\u540E\u679C |
4751
+ |---|--------|----------|----------|
4752
+ | 1 | \u5206\u652F\u6A21\u578B | \u4E3B\u7EBF/\u5F00\u53D1/\u4EFB\u52A1\u5206\u652F\u7684\u547D\u540D\u4E0E\u521B\u5EFA\u89C4\u5219 | \u5206\u652F\u5BF9\u9F50\u73AF\u8282\u65E0\u6CD5\u786E\u5B9A\u4E3B\u7EBF\u5206\u652F\u540D\uFF0C\u6682\u505C\u8BE2\u95EE |
4753
+ | 2 | COMMANDS | \u5B89\u88C5/\u6784\u5EFA/\u7C7B\u578B\u68C0\u67E5/\u6D4B\u8BD5\u7684\u53EF\u6267\u884C\u547D\u4EE4 | \u7F16\u7801\u4E0E\u6D4B\u8BD5\u73AF\u8282\u65E0\u6CD5\u786E\u5B9A\u6267\u884C\u547D\u4EE4\uFF0C\u6682\u505C\u8BE2\u95EE |
4754
+ | 3 | \u6D4B\u8BD5\u8303\u5F0F | \u6D4B\u8BD5\u6846\u67B6\u3001\u547D\u540D\u7EA6\u5B9A\u3001PASS \u5224\u5B9A\u6807\u51C6 | \u5355\u6D4B/E2E \u8BBE\u8BA1\u4E0E\u5F00\u53D1\u73AF\u8282\u7F3A\u5C11\u4F9D\u636E\uFF0C\u6682\u505C\u8BE2\u95EE |
4755
+ | 4 | \u6D41\u7A0B\u6587\u6863\u76EE\u5F55 | PRD/\u6280\u672F\u65B9\u6848/\u6D4B\u8BD5\u8BBE\u8BA1\u7B49\u6D41\u7A0B\u4EA7\u7269\u843D\u76D8\u4F4D\u7F6E | \u6587\u6863\u7C7B\u8282\u70B9\u4EA7\u7269\u65E0\u843D\u70B9\uFF0C\u6682\u505C\u8BE2\u95EE |
4756
+ | 5 | \u67B6\u6784\u6587\u6863\u76EE\u5F55 | \u4E1A\u52A1/\u6280\u672F/E2E/UI \u67B6\u6784\u51B3\u7B56\u6587\u6863\u4F4D\u7F6E | \u8BBE\u8BA1\u73AF\u8282\u7F3A\u5C11\u65E2\u6709\u67B6\u6784\u51B3\u7B56\u8F93\u5165\uFF08\u53EF\u964D\u7EA7\u8DF3\u8FC7\u4F46\u635F\u5931\u5BF9\u9F50\uFF09 |
4757
+ | 6 | E2E \u552F\u4E00\u6267\u884C\u5165\u53E3 | E2E \u6D4B\u8BD5\u552F\u4E00\u5408\u6CD5\u7684\u6267\u884C\u547D\u4EE4/\u811A\u672C | E2E \u5F00\u53D1\u73AF\u8282\u65E0\u6CD5\u786E\u5B9A\u6267\u884C\u65B9\u5F0F\uFF0C\u6682\u505C\u8BE2\u95EE |
4758
+ | 7 | \u6D4B\u8BD5\u5B8C\u6574\u6027\u68C0\u67E5 | \u9632\u5220\u6D4B/\u7981 skip \u7684\u9759\u6001\u68C0\u67E5\u547D\u4EE4 | \u6D4B\u8BD5\u6536\u5C3E\u7F3A\u5C11\u95E8\u7981\u4F9D\u636E\uFF0C\u6682\u505C\u8BE2\u95EE |
4759
+ | 8 | \u547D\u4EE4\u65E5\u5FD7\u843D\u76D8 | \u6784\u5EFA/\u6D4B\u8BD5\u547D\u4EE4\u7684\u65E5\u5FD7\u5F52\u6863\u7EA6\u5B9A | \u547D\u4EE4\u6267\u884C\u65E0\u6CD5\u56DE\u6EAF\uFF0C\u5F52\u6863\u8282\u70B9\u8BC1\u636E\u4E0D\u8DB3 |
4760
+
4761
+ ----------------------------------------------------------------
4762
+ \u4E8C\u3001\u6D41\u7A0B\u6A21\u677F\u83B7\u53D6\u6307\u5F15
4763
+ ----------------------------------------------------------------
4764
+
4765
+ \u65B0\u9879\u76EE\u9700\u8981\u81EA\u5DF1\u7684 DAG \u6D41\u7A0B\u6A21\u677F\uFF08\u6D41\u7A0B\u7ED3\u6784\u4EE5\u9879\u76EE\u5B9E\u4F8B\u5185\u6A21\u677F\u4E3A\u6743\u5A01\uFF09\uFF0C
4766
+ \u4E09\u6761\u83B7\u53D6\u8DEF\u5F84\uFF0C\u8DEF\u5F84 0 \u4E3A\u5168\u65B0\u5B9E\u4F8B\u7684\u63A8\u8350\u8D77\u70B9\uFF1A
4767
+
4768
+ 0. npm \u5305\u5185\u7F6E\u57FA\u7840\u6A21\u677F\uFF1A@siming-org/cli \u5305\u5185\u81EA\u5E26 3 \u4E2A\u7ECF\u8FC7\u9A8C\u8BC1\u7684\u5B8C\u6574
4769
+ \u5DE5\u4F5C\u6D41 bundle\uFF08\u542B\u4F9D\u8D56\u95ED\u5305 skills/agents/\u6A21\u578B\u522B\u540D\uFF0C\u5BFC\u5165\u5373\u5B8C\u6574\u53EF\u7528\uFF09\uFF1A
4770
+ - full_workflow \u5B8C\u6574\u529F\u80FD\u5F00\u53D1\u6D41\u7A0B\uFF08feature \u7C7B\u4EFB\u52A1\u5168\u6D41\u7A0B\uFF09
4771
+ - research_workflow \u8C03\u7814\u4EFB\u52A1\u6D41\u7A0B\uFF08\u4EA7\u51FA\u8C03\u7814\u62A5\u544A\uFF09
4772
+ - quick_fix_workflow \u5FEB\u901F\u4FEE\u590D\u6D41\u7A0B\uFF08bugfix \u7C7B\u4EFB\u52A1\uFF09
4773
+ \u6587\u4EF6\u5B9A\u4F4D\uFF1Anpm \u5168\u5C40\u5B89\u88C5\u5728 <\u5168\u5C40 node_modules>/@siming-org/cli/templates/builtin/\uFF1B
4774
+ tarball \u901A\u9053\u5B89\u88C5\u5728 <\u5B89\u88C5\u76EE\u5F55>/node_modules/@siming-org/cli/templates/builtin/
4775
+ \uFF08\u5982 ~/siming-prod\uFF09\u3002\u6587\u4EF6\u540D\u5F62\u5982 full_workflow.bundle.json\u3002
4776
+ \u5B89\u88C5\uFF08\u4E8C\u9009\u4E00\uFF09\uFF1A
4777
+ - CLI \u547D\u4EE4\uFF1Asiming dag template import <bundle \u6587\u4EF6\u8DEF\u5F84>
4778
+ \uFF08\u6309\u5185\u5BB9\u81EA\u52A8\u8BC6\u522B bundle \u683C\u5F0F\uFF0C\u9884\u68C0+\u6267\u884C\u53CC\u9636\u6BB5\uFF1B--project <key|id> \u6307\u5B9A
4779
+ \u76EE\u6807\u9879\u76EE\uFF0C\u7F3A\u7701\u7528\u5DE5\u4F5C\u533A defaultProject\uFF1B--plan \u53EA\u9884\u68C0\u4E0D\u6267\u884C\uFF1B
4780
+ --overwrite-deps \u51B2\u7A81\u4F9D\u8D56\u5F3A\u5236\u8986\u76D6\uFF09
4781
+ - Web \u7BA1\u7406\u53F0\uFF1ADAG \u6A21\u677F\u9875\u5BFC\u5165\u5411\u5BFC\u4E0A\u4F20\u540C\u4E00 bundle \u6587\u4EF6
4782
+ \u901A\u9053\u8FB9\u754C\uFF1AMCP siming_template import \u4EC5\u652F\u6301\u5355\u6A21\u677F YAML\uFF08\u4E0D\u5E26\u4F9D\u8D56\u95ED\u5305\uFF09\uFF0C
4783
+ \u5B8C\u6574\u5B89\u88C5\u8D70 CLI \u547D\u4EE4\u6216 Web \u5411\u5BFC\u3002
4784
+ \u5BFC\u5165\u540E\u5373\u4E3A\u666E\u901A\u8D44\u4EA7\uFF1A\u53EF\u7F16\u8F91/\u590D\u5236\u5B9A\u5236\uFF1B\u6A21\u578B\u522B\u540D\u5EFA\u8BAE\u6309\u672C\u9879\u76EE\u6A21\u578B\u914D\u7F6E\u4FEE\u6539\u3002
4785
+
4786
+ 1. \u5B9E\u4F8B\u5185\u590D\u5236\uFF1A\u82E5\u672C siming \u5B9E\u4F8B\u5DF2\u6709\u7ED3\u6784\u53EF\u53C2\u8003\u7684\u9879\u76EE\u6A21\u677F\uFF0C
4787
+ \u5728 Web \u7BA1\u7406\u53F0 DAG \u6A21\u677F\u9875\u4F7F\u7528\u590D\u5236\u529F\u80FD\uFF08\u6E90\u6A21\u677F\u4E0D\u52A8\uFF0C\u526F\u672C\u53EF\u7F16\u8F91\uFF09\u3002
4788
+
4789
+ 2. \u8DE8\u5B9E\u4F8B\u8FC1\u79FB\uFF1A\u4ECE\u6E90\u5B9E\u4F8B\u53D6\u6A21\u677F\u5B8C\u6574\u7ED3\u6784\uFF08siming dag template show
4790
+ <\u6A21\u677F> --format json\uFF0C\u542B\u8282\u70B9/\u8FDE\u7EBF/\u63D0\u793A\u8BCD\u5168\u91CF\uFF09\uFF0C\u6574\u7406\u4E3A YAML \u540E\u5728\u76EE\u6807
4791
+ \u5B9E\u4F8B\u6267\u884C siming dag template import <file.yaml> \u5BFC\u5165\uFF1B\u6216\u6574\u7406\u4E3A
4792
+ export \u6761\u76EE\u6587\u4EF6\uFF08dags \u6570\u7EC4\uFF09\u7ECF siming export apply \u4E0A\u4F20\u3002
4793
+
4794
+ AI \u7F16\u7A0B\u4EE3\u7406\u53EF\u7ECF MCP \u5DE5\u5177\u64CD\u4F5C\uFF1Asiming_template\uFF08list/show/import\uFF09\u3002
4795
+
4796
+ ----------------------------------------------------------------
4797
+ \u4E09\u3001\u9879\u76EE\u7EA7\u8D44\u4EA7\u6307\u8DEF
4798
+ ----------------------------------------------------------------
4799
+
4800
+ \u4EE5\u4E0B\u4E24\u7C7B\u9879\u76EE\u4F5C\u7528\u57DF skill \u8D44\u4EA7\u5EFA\u8BAE\u6BCF\u4E2A\u63A5\u5165\u9879\u76EE\u81EA\u5EFA\u4E00\u4EFD
4801
+ \uFF08\u6B64\u5904\u53EA\u6307\u8DEF\u4E0D\u590D\u5236\u5185\u5BB9\uFF0C\u7248\u672C\u4EE5\u9879\u76EE\u5B9E\u4F8B\u5185\u5B9E\u9645\u4E3A\u51C6\uFF09\uFF1A
4802
+
4803
+ 1. task-create \u2014\u2014 \u4EFB\u52A1\u521B\u5EFA\u5165\u53E3\u6307\u5F15\uFF1A\u672C\u9879\u76EE\u300C\u4EFB\u52A1\u7C7B\u578B \xD7 \u8F68\u9053 \u2192 \u6A21\u677F\u4E0E
4804
+ \u526A\u679D\u300D\u5339\u914D\u89C4\u5219\u7684\u5B9A\u5236\u7248\uFF08\u542B\u4FEE\u8BA2\u6E05\u5355\uFF09\u3002\u83B7\u53D6\u65B9\u5F0F\uFF1A\u4ECE\u65E2\u6709\u9879\u76EE\u590D\u5236\u540E
4805
+ \u6309\u672C\u9879\u76EE\u6A21\u677F\u5217\u8868\u4FEE\u8BA2\uFF0C\u6216\u6309\u540C\u540D\u8D44\u4EA7\u7ED3\u6784\u65B0\u5EFA\u3002
4806
+
4807
+ 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
4808
+ \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
4809
+
4810
+ \u8D44\u4EA7\u521B\u5EFA/\u590D\u5236\uFF1AWeb \u7BA1\u7406\u53F0\u6216 siming skill / siming agent \u547D\u4EE4\u7EC4\uFF1B
4811
+ \u8DE8\u5B9E\u4F8B\u8FC1\u79FB\u8D70 siming export / siming install\u3002
4812
+
4813
+ ----------------------------------------------------------------
4814
+ \u56DB\u3001\u63A5\u5165\u9A8C\u8BC1\u6B65\u9AA4
4815
+ ----------------------------------------------------------------
4816
+
4817
+ \u63A5\u5165\u6210\u529F\u7684\u5224\u5B9A\u52A8\u4F5C\u2014\u2014\u521B\u5EFA\u9996\u4E2A\u4EFB\u52A1\u5E76\u8DD1\u901A\u9996\u8282\u70B9\uFF1A
4818
+
4819
+ 1. \u786E\u8BA4 server \u53EF\u8FBE\uFF1Asiming healthcheck\uFF08\u6216 siming doctor \u5168\u9762\u81EA\u68C0\uFF09
4820
+ 2. \u521B\u5EFA\u9996\u4EFB\u52A1\uFF1A\u52A0\u8F7D task-create skill\uFF08\u6309\u5176\u5339\u914D\u89C4\u5219\u9009\u6A21\u677F\u4E0E\u526A\u679D\uFF09\uFF0C
4821
+ \u6216\u7ECF MCP \u5DE5\u5177 siming_task\uFF08action: create\uFF09
4822
+ 3. \u63A8\u8FDB\u9996\u8282\u70B9\uFF1A\u6309\u4EFB\u52A1 context \u8FD4\u56DE\u7684\u8282\u70B9\u63D0\u793A\u8BCD\u6267\u884C\u5E76 advance
4823
+ 4. \u9996\u8282\u70B9\u8DD1\u901A = \u9879\u76EE\u58F0\u660E\u3001\u6A21\u677F\u3001\u8D44\u4EA7\u3001\u94FE\u8DEF\u5168\u90E8\u5C31\u7EEA
4824
+
4825
+ ================================================================
4826
+ \u672C\u6307\u5BFC\u968F siming CLI \u7248\u672C\u53D1\u5E03\u6F14\u8FDB\uFF08\u7EAF\u672C\u5730\u9759\u6001\u6587\u672C\uFF0C\u96F6\u7F51\u7EDC\u4F9D\u8D56\uFF09\u3002
4827
+ ================================================================
4828
+ `;
4829
+ function getGuideText() {
4830
+ return GUIDE_TEXT;
4831
+ }
4832
+
4833
+ // src/commands/guide.ts
4834
+ function createGuideCommand() {
4835
+ const guide = new Command13("guide").description("Print the onboarding guide for connecting a new project to siming workflows").allowExcessArguments(false).action(() => {
4836
+ console.log(getGuideText());
4837
+ });
4838
+ return guide;
4839
+ }
4840
+
4841
+ // src/commands/settings/command.ts
4842
+ import { Command as Command14 } from "commander";
4197
4843
  import { EnumRegistryCategorySchema as EnumRegistryCategorySchema2, EnumRegistryUpdateSchema as EnumRegistryUpdateSchema2 } from "@siming-org/core";
4198
4844
  function createSettingsCommand() {
4199
- const settings = new Command13("settings").description("Settings (enum registries)");
4845
+ const settings = new Command14("settings").description("Settings (enum registries)");
4200
4846
  withCommonOpts(settings.command("enums [category]"), "fancy").description("Show enum registry (all 7 categories, or one category)").action(async (category, opts) => {
4201
4847
  const client = createClient(opts.url);
4202
4848
  const catR = category ? EnumRegistryCategorySchema2.safeParse(category) : null;
@@ -4245,13 +4891,13 @@ function readStdin() {
4245
4891
  }
4246
4892
 
4247
4893
  // src/commands/server/command.ts
4248
- import { Command as Command14 } from "commander";
4894
+ import { Command as Command15 } from "commander";
4249
4895
  import { spawn as spawn2 } from "child_process";
4250
4896
  import { VERSION as VERSION4, SIMING_CONFIG_KEYS as SIMING_CONFIG_KEYS2 } from "@siming-org/core";
4251
4897
 
4252
4898
  // src/commands/server/daemon.ts
4253
4899
  import { execFileSync } from "child_process";
4254
- import { closeSync, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync9, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
4900
+ import { closeSync, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync4, openSync, readFileSync as readFileSync11, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
4255
4901
  import { join as join6, resolve as resolve2 } from "path";
4256
4902
  import { spawn } from "child_process";
4257
4903
 
@@ -4281,7 +4927,7 @@ var FALLBACK_CLK_TCK = 100;
4281
4927
  function ensureRuntimeDir() {
4282
4928
  const st = lstatSync(runtimeDir(), { throwIfNoEntry: false });
4283
4929
  if (st === void 0) {
4284
- mkdirSync5(runtimeDir(), { mode: 448, recursive: true });
4930
+ mkdirSync4(runtimeDir(), { mode: 448, recursive: true });
4285
4931
  return;
4286
4932
  }
4287
4933
  if (st.isSymbolicLink()) {
@@ -4305,7 +4951,7 @@ function readPidFile() {
4305
4951
  try {
4306
4952
  const st = lstatSync(pidfilePath(), { throwIfNoEntry: false });
4307
4953
  if (st === void 0 || st.isSymbolicLink()) return null;
4308
- const parsed = JSON.parse(readFileSync9(pidfilePath(), "utf-8").trim());
4954
+ const parsed = JSON.parse(readFileSync11(pidfilePath(), "utf-8").trim());
4309
4955
  if (typeof parsed.pid !== "number" || typeof parsed.startedAt !== "number" || typeof parsed.port !== "number") {
4310
4956
  return null;
4311
4957
  }
@@ -4333,7 +4979,7 @@ function writePidFile(info2) {
4333
4979
  }
4334
4980
  }
4335
4981
  const tmp = `${pidfilePath()}.tmp-${process.pid}`;
4336
- writeFileSync5(tmp, `${JSON.stringify(info2)}
4982
+ writeFileSync4(tmp, `${JSON.stringify(info2)}
4337
4983
  `, "utf-8");
4338
4984
  renameSync3(tmp, pidfilePath());
4339
4985
  return true;
@@ -4346,7 +4992,7 @@ function removePidFile(expectedPid) {
4346
4992
  }
4347
4993
  function readCmdline(pid) {
4348
4994
  try {
4349
- const raw = readFileSync9(`/proc/${pid}/cmdline`);
4995
+ const raw = readFileSync11(`/proc/${pid}/cmdline`);
4350
4996
  const joined = raw.toString().split("\0").filter((s) => s.length > 0).join(" ");
4351
4997
  if (joined.length > 0) return joined;
4352
4998
  } catch {
@@ -4375,7 +5021,7 @@ function isSimingDaemonCmdline(cmdline, expectedEntry) {
4375
5021
  }
4376
5022
  function readProcessStartMs(pid) {
4377
5023
  try {
4378
- const stat = readFileSync9(`/proc/${pid}/stat`, "utf-8");
5024
+ const stat = readFileSync11(`/proc/${pid}/stat`, "utf-8");
4379
5025
  const rest = stat.slice(stat.lastIndexOf(")") + 2);
4380
5026
  const fields = rest.split(" ");
4381
5027
  const starttimeJiffies = Number(fields[19]);
@@ -4404,7 +5050,7 @@ function readProcessStartMs(pid) {
4404
5050
  }
4405
5051
  function readBtimeFromProcStat() {
4406
5052
  try {
4407
- const stat = readFileSync9("/proc/stat", "utf-8");
5053
+ const stat = readFileSync11("/proc/stat", "utf-8");
4408
5054
  for (const line of stat.split("\n")) {
4409
5055
  if (line.startsWith("btime ")) {
4410
5056
  const v = Number(line.slice(6).trim());
@@ -4455,7 +5101,7 @@ function sleep(ms) {
4455
5101
  function readLogTail(lines = 30) {
4456
5102
  const st = lstatSync(logfilePath(), { throwIfNoEntry: false });
4457
5103
  if (st === void 0 || st.isSymbolicLink()) return null;
4458
- const content = readFileSync9(logfilePath(), "utf-8");
5104
+ const content = readFileSync11(logfilePath(), "utf-8");
4459
5105
  const all = content.split("\n");
4460
5106
  if (all.at(-1) === "") all.pop();
4461
5107
  return all.slice(-lines);
@@ -4521,7 +5167,7 @@ function displayUrl(host, port) {
4521
5167
  // src/commands/server/command.ts
4522
5168
  var MONGO_ERROR_PATTERN = /server selection|ECONNREFUSED|ENOTFOUND|EACCES|authentication/i;
4523
5169
  function createServerCommand() {
4524
- const server = new Command14("server").description("\u7BA1\u7406 siming \u670D\u52A1\uFF08API \u4E0E Web UI \u540C\u8FDB\u7A0B\u540C\u7AEF\u53E3\uFF09");
5170
+ const server = new Command15("server").description("\u7BA1\u7406 siming \u670D\u52A1\uFF08API \u4E0E Web UI \u540C\u8FDB\u7A0B\u540C\u7AEF\u53E3\uFF09");
4525
5171
  server.command("start").description("\u542F\u52A8 siming \u670D\u52A1\uFF08\u9ED8\u8BA4\u5B88\u62A4\u6A21\u5F0F\uFF0C\u65E5\u5FD7\u5199\u5165 /tmp/siming/\uFF09").option("--port <port>", "\u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4 7777\uFF1B\u4E5F\u53EF\u7ECF PORT \u73AF\u5883\u53D8\u91CF/\u914D\u7F6E\u6587\u4EF6\u914D\u7F6E\uFF09").option("--mongo-uri <uri>", "MongoDB \u8FDE\u63A5\u4E32\uFF08\u4E5F\u53EF\u7ECF SIMING_MONGO_URI/\u914D\u7F6E\u6587\u4EF6\u914D\u7F6E\uFF09").option("--foreground", "\u524D\u53F0\u8FD0\u884C\uFF08\u8C03\u8BD5/systemd \u573A\u666F\uFF09\uFF0CCtrl+C \u4F18\u96C5\u9000\u51FA\uFF1B\u4E0D\u5199 pidfile", false).action(async (opts) => {
4526
5172
  process.exitCode = await startAction(opts);
4527
5173
  });
@@ -4873,7 +5519,7 @@ function reportPortConflict(port) {
4873
5519
  }
4874
5520
 
4875
5521
  // src/index.ts
4876
- var program = new Command15();
5522
+ var program = new Command16();
4877
5523
  program.name("siming").description("\u53F8\u547D \xB7 Siming \u2014 AI coding workflow management platform").version(VERSION5);
4878
5524
  program.command("healthcheck").description("Check if the siming server is reachable").option("--url <url>", "server base URL").action(async (opts) => {
4879
5525
  await healthcheckCommand(opts);
@@ -4892,6 +5538,7 @@ program.addCommand(createExportCommand());
4892
5538
  program.addCommand(createInstallCommand());
4893
5539
  program.addCommand(createInitCommand());
4894
5540
  program.addCommand(createDoctorCommand());
5541
+ program.addCommand(createGuideCommand());
4895
5542
  program.addCommand(createSettingsCommand());
4896
5543
  program.addCommand(createServerCommand());
4897
5544
  export {