@siming-org/cli 0.7.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +50 -10
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1263,6 +1263,9 @@ function readStdinLine(stream) {
1263
1263
  async function handleCreateIssue(client, input) {
1264
1264
  return client.postJson("/api/issues", input);
1265
1265
  }
1266
+ async function handleDoneIssue(client, issueId, note) {
1267
+ return client.postJson(`/api/issues/${issueId}/done`, note !== void 0 ? { note } : {});
1268
+ }
1266
1269
  async function handleListIssues(client, filters) {
1267
1270
  const params = new URLSearchParams();
1268
1271
  if (filters.status) params.set("status", filters.status);
@@ -1538,6 +1541,8 @@ var issueArgs = {
1538
1541
  // create
1539
1542
  title: z3.string().optional(),
1540
1543
  description: z3.string().optional(),
1544
+ /** create 必填(T202609200001):人类审批原话逐字(1-500 字)——per-action 必填以 ISSUE_FIELD_SPECS.create.required 为权威 */
1545
+ approved: z3.string().optional(),
1541
1546
  // 公共:create 缺省按工作区 defaultProject(key|id 双形态通道层归一,失效报错)/ query 过滤(空/未传不过滤)
1542
1547
  projectId: z3.string().optional(),
1543
1548
  // query:view 缺省 open(有效未跟进完);与 REST 词汇统一(status/taskId 指定时切对应过滤)
@@ -1675,7 +1680,7 @@ var TASK_FIELD_SPECS = {
1675
1680
  "archnote-add": { required: ["taskId"], optional: ["text", "textItems"] }
1676
1681
  };
1677
1682
  var ISSUE_FIELD_SPECS = {
1678
- create: { required: ["title"], optional: ["description", "projectId"] },
1683
+ create: { required: ["title", "approved"], optional: ["description", "projectId"] },
1679
1684
  query: { required: [], optional: ["view", "status", "taskId", "projectId", "page", "limit"] }
1680
1685
  };
1681
1686
  function createMcpServer() {
@@ -2056,7 +2061,7 @@ function createMcpServer() {
2056
2061
  );
2057
2062
  server.tool(
2058
2063
  "siming_issue",
2059
- `\u95EE\u9898\u6C60\u5DE5\u5177\uFF08T202609150002\uFF09\uFF1A\u5C0F\u95EE\u9898\u4F4E\u6210\u672C\u5165\u6C60\uFF0C\u6C89\u6DC0\u540E\u7EDF\u4E00\u6574\u7406\u8F6C\u4EFB\u52A1\uFF08\u8F6C\u4EFB\u52A1/\u6574\u7406\u91CD\u4EA4\u4E92\u8D70 CLI siming issue convert \u6216 Web\uFF0C\u4E0D\u5728\u672C\u5DE5\u5177\u9762\uFF09\u3002action\uFF1Acreate(title \u5FC5\u586B 1-200 \u5B57\uFF1B\u53EF\u9009 description\u3001projectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\u4E3A 24-hex id\uFF08hex \u96F6\u7F51\u7EDC\u5F00\u9500\u76F4\u901A\uFF09\uFF1B\u663E\u5F0F\u6307\u5B9A\u89E3\u6790\u5931\u8D25\u62A5\u9519\u4E0D\u515C\u5E95\uFF1B\u7F3A\u7701\u94FE\uFF1A\u672A\u4F20\u6216\u7A7A\u4E32\u65F6\u6309\u5DE5\u4F5C\u533A defaultProject \u89E3\u6790\uFF08\u5931\u6548\u62A5\u9519\uFF09\uFF0C\u65E0\u914D\u7F6E\u65F6\u4E0D\u4F20 projectId \u7531 server \u6309 key=default \u515C\u5E95\uFF1B\u5F55\u5165\u540E source=mcp)\uFF1Bquery(\u53EF\u9009 view=open|all\u2014\u2014\u7F3A\u7701 open=\u6709\u6548\u672A\u8DDF\u8FDB\u5B8C\uFF0Call=\u5168\u91CF\uFF1Bstatus \u8FC7\u6EE4\u2014\u2014\u663E\u5F0F\u6307\u5B9A\u65F6\u4F18\u5148\u4E8E view\uFF0C\u53EF\u67E5\u5DF2\u53D6\u6D88/\u5DF2\u5B8C\u7ED3\uFF1BtaskId=\u4EFB\u52A1\u53CD\u67E5\uFF1BprojectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\uFF0C\u7A7A/\u672A\u4F20\u4E0D\u8FC7\u6EE4\uFF08\u663E\u5F0F\u89E3\u6790\u5931\u8D25\u62A5\u9519\uFF09\uFF1Bpage\u22651/limit 1-500\uFF1B\u54CD\u5E94 items \u542B progress {done,cancelled,total})\u3002\u8C03\u7528\u65B9\u5E94\u5728 fieldMask \u4E2D\u5217\u51FA\u672C\u6B21\u771F\u5B9E\u63D0\u4F9B\u7684\u53EF\u9009\u5B57\u6BB5\uFF0Cmask \u5916\u7531\u5BBF\u4E3B\u81EA\u52A8\u586B\u5145\u7684\u7A7A\u4E32\u3001\u7A7A\u6570\u7EC4\u3001false\u30010 \u5747\u5FFD\u7565\uFF1B\u5404 action \u56FA\u5B9A\u5FC5\u586B\u5B57\u6BB5\u65E0\u9700\u5199\u5165 mask\u3002`,
2064
+ `\u95EE\u9898\u6C60\u5DE5\u5177\uFF08T202609150002\uFF1BT202609200001 \u5F55\u5165\u5BA1\u6279\u95E8\u69DB\uFF09\uFF1A\u5C0F\u95EE\u9898\u4F4E\u6210\u672C\u5165\u6C60\uFF0C\u6C89\u6DC0\u540E\u7EDF\u4E00\u6574\u7406\u8F6C\u4EFB\u52A1\uFF08\u8F6C\u4EFB\u52A1/\u76F4\u63A5\u6807\u8BB0\u5B8C\u6210\u7B49\u6574\u7406\u91CD\u4EA4\u4E92\u8D70 CLI siming issue convert / siming issue done \u6216 Web\uFF0C\u4E0D\u5728\u672C\u5DE5\u5177\u9762\uFF09\u3002action\uFF1Acreate(title \u5FC5\u586B 1-200 \u5B57\uFF1Bapproved \u5FC5\u586B 1-500 \u5B57\u2014\u2014\u4EBA\u7C7B\u5BA1\u6279\u539F\u8BDD\u9010\u5B57\u5F15\u7528\uFF1A\u5F55\u5165\u524D\u5FC5\u987B\u5148\u5411\u7528\u6237\u5B8C\u6574\u5448\u73B0\u95EE\u9898\uFF08\u73B0\u8C61/\u6839\u56E0/\u5F71\u54CD/\u5EFA\u8BAE\uFF09\u5E76\u83B7\u7528\u6237\u660E\u786E\u6279\u51C6\uFF0C\u503C = \u7528\u6237\u6279\u51C6\u65F6\u8F93\u5165\u7684\u539F\u8BDD\uFF08\u5982\u300COK\uFF0C\u8BB0\u5F55\u300D\uFF09\uFF0C\u7981\u6B62\u4EE3\u586B\u3001\u7F16\u9020\u6216\u4EE5\u8BC4\u4F30\u6027\u8BED\u8A00\u4EE3\u66FF\uFF1B\u4F2A\u9020\u5C5E\u8FDD\u89C4\u5E76\u7559\u5BA1\u8BA1\u75D5\u8FF9\uFF1B\u539F\u8BDD\u843D\u5E93\u4F9B\u4E8B\u540E\u5BA1\u8BA1\uFF08query \u4E0E Web \u8BE6\u60C5\u9875\u53EF\u67E5\uFF09\uFF1B\u53EF\u9009 description\u3001projectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\u4E3A 24-hex id\uFF08hex \u96F6\u7F51\u7EDC\u5F00\u9500\u76F4\u901A\uFF09\uFF1B\u663E\u5F0F\u6307\u5B9A\u89E3\u6790\u5931\u8D25\u62A5\u9519\u4E0D\u515C\u5E95\uFF1B\u7F3A\u7701\u94FE\uFF1A\u672A\u4F20\u6216\u7A7A\u4E32\u65F6\u6309\u5DE5\u4F5C\u533A defaultProject \u89E3\u6790\uFF08\u5931\u6548\u62A5\u9519\uFF09\uFF0C\u65E0\u914D\u7F6E\u65F6\u4E0D\u4F20 projectId \u7531 server \u6309 key=default \u515C\u5E95\uFF1B\u5F55\u5165\u540E source=mcp\uFF0C\u7F3A approved \u670D\u52A1\u7AEF 400 \u5E76\u8FD4\u56DE\u81EA\u89E3\u91CA\u6587\u6848)\uFF1Bquery(\u53EF\u9009 view=open|all\u2014\u2014\u7F3A\u7701 open=\u6709\u6548\u672A\u8DDF\u8FDB\u5B8C\uFF0Call=\u5168\u91CF\uFF1Bstatus \u8FC7\u6EE4\u2014\u2014pending|partial|converted|cancelled|done\uFF0C\u663E\u5F0F\u6307\u5B9A\u65F6\u4F18\u5148\u4E8E view\uFF0C\u53EF\u67E5\u5DF2\u53D6\u6D88/\u5DF2\u5B8C\u6210\uFF1BtaskId=\u4EFB\u52A1\u53CD\u67E5\uFF1BprojectId\u2014\u2014key|id \u53CC\u5F62\u6001\uFF0C\u901A\u9053\u5C42\u81EA\u52A8\u5F52\u4E00\uFF0C\u7A7A/\u672A\u4F20\u4E0D\u8FC7\u6EE4\uFF08\u663E\u5F0F\u89E3\u6790\u5931\u8D25\u62A5\u9519\uFF09\uFF1Bpage\u22651/limit 1-500\uFF1B\u54CD\u5E94 items \u542B progress {done,cancelled,total})\u3002\u8C03\u7528\u65B9\u5E94\u5728 fieldMask \u4E2D\u5217\u51FA\u672C\u6B21\u771F\u5B9E\u63D0\u4F9B\u7684\u53EF\u9009\u5B57\u6BB5\uFF0Cmask \u5916\u7531\u5BBF\u4E3B\u81EA\u52A8\u586B\u5145\u7684\u7A7A\u4E32\u3001\u7A7A\u6570\u7EC4\u3001false\u30010 \u5747\u5FFD\u7565\uFF1B\u5404 action \u56FA\u5B9A\u5FC5\u586B\u5B57\u6BB5\u65E0\u9700\u5199\u5165 mask\u3002`,
2060
2065
  issueArgs,
2061
2066
  async (rawArgs) => {
2062
2067
  const masked = applyFieldMask(rawArgs, ISSUE_FIELD_SPECS);
@@ -2064,9 +2069,9 @@ function createMcpServer() {
2064
2069
  const args = masked.args;
2065
2070
  switch (args.action) {
2066
2071
  case "create": {
2067
- const { title } = args;
2068
- if (title === void 0) {
2069
- return requireError("create", ["title"], args);
2072
+ const { title, approved } = args;
2073
+ if (title === void 0 || approved === void 0) {
2074
+ return requireError("create", ["title", "approved"], args);
2070
2075
  }
2071
2076
  const projectR = await resolveScopedProject(client, args.projectId, "ws-default", { channel: "mcp" });
2072
2077
  if (!projectR.success) return mcpContent(projectR);
@@ -2075,7 +2080,8 @@ function createMcpServer() {
2075
2080
  await handleCreateIssue(client, {
2076
2081
  title,
2077
2082
  ...args.description !== void 0 ? { description: args.description } : {},
2078
- ...projectId !== void 0 ? { projectId } : {}
2083
+ ...projectId !== void 0 ? { projectId } : {},
2084
+ approved
2079
2085
  })
2080
2086
  );
2081
2087
  }
@@ -7252,7 +7258,15 @@ async function buildInstallPlan(client, scope, projectId, only) {
7252
7258
  if (!agentsR.success) return agentsR;
7253
7259
  const t = resolveInstallTargets(scope);
7254
7260
  if (t.error || !t.targets) {
7255
- return { success: false, error: { message: t.error ?? "cannot resolve install targets", httpStatus: 0 } };
7261
+ return {
7262
+ success: false,
7263
+ error: {
7264
+ message: t.error ?? "cannot resolve install targets",
7265
+ httpStatus: 0,
7266
+ // T202609190002:错误四要素契约补齐(hint 缺失导致 E2E_CLI_WS_INSTALL_002 失败)
7267
+ hint: "run `siming init --project <key|id>` inside the project workspace (containing .siming/), or retry with --scope global"
7268
+ }
7269
+ };
7256
7270
  }
7257
7271
  const dir = t.targets.dir;
7258
7272
  const items = [];
@@ -8704,7 +8718,7 @@ function parseDeclarationsMap(spec) {
8704
8718
  }
8705
8719
  function createIssueCommand() {
8706
8720
  const issue = new Command18("issue").description("Issue pool: record \u2192 organize \u2192 convert to tasks");
8707
- withCommonOpts(issue.command("add"), "fancy").description("Record an issue into the pool (source=cli)").argument("[title]", "issue title (or use --title)").option("--title <t>", "issue title (1-200 chars)").option("--description <d>", "issue description (optional)").option("--project <key|id>", "projectId (key|id; falls back to workspace defaultProject, then server default project)").action(async (titleArg, opts) => {
8721
+ withCommonOpts(issue.command("add"), "fancy").description("Record an issue into the pool (source=cli; requires --approved human approval quote)").argument("[title]", "issue title (or use --title)").option("--title <t>", "issue title (1-200 chars)").option("--description <d>", "issue description (optional)").option("--approved <text>", `human approval quote verbatim (1-500 chars; e.g. user's literal reply "OK, record it")`).option("--project <key|id>", "projectId (key|id; falls back to workspace defaultProject, then server default project)").action(async (titleArg, opts) => {
8708
8722
  const client = createClient(opts.url);
8709
8723
  const title = opts.title ?? titleArg;
8710
8724
  if (title === void 0 || title.length === 0) {
@@ -8714,6 +8728,26 @@ function createIssueCommand() {
8714
8728
  });
8715
8729
  return;
8716
8730
  }
8731
+ if (opts.approved === void 0 || opts.approved.trim() === "") {
8732
+ renderResult("json", {
8733
+ success: false,
8734
+ error: {
8735
+ message: 'issue add \u987B\u643A\u5E26 --approved "<\u4EBA\u7C7B\u5BA1\u6279\u539F\u8BDD>"\uFF08\u5982\u7528\u6237\u56DE\u590D\u7684\u300COK\uFF0C\u8BB0\u5F55\u300D\u539F\u6587\u9010\u5B57\uFF09\u2014\u2014AI \u4E0D\u5F97\u672A\u7ECF\u7528\u6237\u6279\u51C6\u5F55\u5165 issue\uFF0C\u4E5F\u4E0D\u5F97\u4EE3\u586B/\u7F16\u9020\u5BA1\u6279\u539F\u8BDD',
8736
+ httpStatus: 0
8737
+ }
8738
+ });
8739
+ return;
8740
+ }
8741
+ if (opts.approved.length > 500) {
8742
+ renderResult("json", {
8743
+ success: false,
8744
+ error: {
8745
+ message: `--approved \u8D85\u51FA 500 \u5B57\u4E0A\u9650\uFF08\u5F53\u524D ${String(opts.approved.length)} \u5B57\uFF09\u2014\u2014\u5BA1\u6279\u539F\u8BDD\u987B\u4E3A\u7528\u6237\u539F\u6587\u4E14 \u2264500 \u5B57\uFF0C\u53EF\u8BF7\u7528\u6237\u7ED9\u51FA\u7B80\u77ED\u660E\u786E\u7684\u6279\u51C6\u8868\u8FF0\u540E\u5F15\u7528\u5176\u539F\u6587`,
8746
+ httpStatus: 0
8747
+ }
8748
+ });
8749
+ return;
8750
+ }
8717
8751
  const projectR = await resolveScopedProject(client, opts.project, "ws-default", { commandLabel: "siming issue add" });
8718
8752
  if (!projectR.success) {
8719
8753
  renderResult(opts.format ?? "fancy", projectR);
@@ -8723,11 +8757,12 @@ function createIssueCommand() {
8723
8757
  const result = await handleCreateIssue(client, {
8724
8758
  title,
8725
8759
  ...opts.description !== void 0 ? { description: opts.description } : {},
8726
- ...projectId !== void 0 ? { projectId } : {}
8760
+ ...projectId !== void 0 ? { projectId } : {},
8761
+ approved: opts.approved
8727
8762
  });
8728
8763
  renderResult(opts.format ?? "fancy", result);
8729
8764
  });
8730
- withCommonOpts(issue.command("list"), "table").option("--status <s>", "filter by issue status (pending|partial|converted|cancelled)").option("--source <s>", "filter by source channel (mcp|cli|web)").option("--project <key|id>", "filter by projectId (key|id)").option("--task <taskId>", "filter by linked task").option("--q <keyword>", "search in title/description").option("--view <v>", "view: all|open (default all; open = \u6709\u6548\u672A\u8DDF\u8FDB\u5B8C)").option("--page <n>", "page number (default 1)", "1").option("--limit <n>", `page size (default ${PAGE_DEFAULT2}, max ${PAGE_MAX2})`).option("--all", `show all (limit ${PAGE_MAX2})`).description("List issues (with progress aggregation done/cancelled/total)").action(async (opts) => {
8765
+ withCommonOpts(issue.command("list"), "table").option("--status <s>", "filter by issue status (pending|partial|converted|cancelled|done)").option("--source <s>", "filter by source channel (mcp|cli|web)").option("--project <key|id>", "filter by projectId (key|id)").option("--task <taskId>", "filter by linked task").option("--q <keyword>", "search in title/description").option("--view <v>", "view: all|open (default all; open = \u6709\u6548\u672A\u8DDF\u8FDB\u5B8C)").option("--page <n>", "page number (default 1)", "1").option("--limit <n>", `page size (default ${PAGE_DEFAULT2}, max ${PAGE_MAX2})`).option("--all", `show all (limit ${PAGE_MAX2})`).description("List issues (with progress aggregation done/cancelled/total)").action(async (opts) => {
8731
8766
  const client = createClient(opts.url);
8732
8767
  const filters = {};
8733
8768
  if (opts.status) filters.status = opts.status;
@@ -8829,6 +8864,11 @@ function createIssueCommand() {
8829
8864
  const result = await handleCancelIssue(client, issueId, opts.reason);
8830
8865
  renderResult(opts.format ?? "fancy", result);
8831
8866
  });
8867
+ withCommonOpts(issue.command("done"), "fancy").argument("<issueId>", "issue id (I-prefixed)").option("--note <n>", "completion note (optional, \u2264500 chars \u2014 e.g. \u5728\u54EA\u4E2A\u4EFB\u52A1/\u54EA\u6B21\u6539\u52A8\u4E2D\u987A\u5E26\u89E3\u51B3)").description("Mark an issue as done directly (terminal state; keep taskLinks)").action(async (issueId, opts) => {
8868
+ const client = createClient(opts.url);
8869
+ const result = await handleDoneIssue(client, issueId, opts.note);
8870
+ renderResult(opts.format ?? "fancy", result);
8871
+ });
8832
8872
  withCommonOpts(issue.command("convert"), "fancy").requiredOption("--issue-ids <ids>", "comma-separated issue ids (or repeatable flag)", collectArgs, []).option("--declaration <mode>", "uniform declaration for all issues: all|partial (default all)").option("--declarations <map>", "per-issue declarations: id1:all,id2:partial (overrides --declaration)").requiredOption("--title <t>", "new task title").requiredOption("--template <code|name|id>", "DAG template code (preferred), name, or 24-hex id").requiredOption("--track <t>", "task track (backend|ui|mixed|research)").option("--type <t>", "task type (feature|bugfix|ui-tweak|research)").option("--skip <ids>", "node ids to prune (comma-separated, repeatable)", collectArgs, []).option("--project <key|id>", "projectId (key|id; issues and new task must belong to it)").description("Convert issues to a task (single group: N issues \u2192 1 task; split = multiple calls)").action(async (opts) => {
8833
8873
  const client = createClient(opts.url);
8834
8874
  const issueIds = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siming-org/cli",
3
- "version": "0.7.4",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "author": "Wuchao",
6
6
  "engines": {
@@ -27,8 +27,8 @@
27
27
  "picocolors": "^1.1.1",
28
28
  "yaml": "^2.6.0",
29
29
  "zod": "^4.4.3",
30
- "@siming-org/core": "0.7.4",
31
- "@siming-org/server": "0.7.4"
30
+ "@siming-org/core": "0.8.0",
31
+ "@siming-org/server": "0.8.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "tsup": "^8.3.5",