@zentodo/cli 0.1.6 → 0.1.8

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/bin.cjs CHANGED
@@ -4061,6 +4061,24 @@ var pomoCapabilities = [
4061
4061
  cli: { group: "pomo", command: "history" },
4062
4062
  tool: { readOnlyHint: true, idempotentHint: true }
4063
4063
  },
4064
+ {
4065
+ id: "pomo.focus-stats",
4066
+ domain: "pomo",
4067
+ action: "focus-stats",
4068
+ summary: "\u4E13\u6CE8\u65F6\u957F\u7EDF\u8BA1(\u65F6\u95F4\u7A97)\u3002",
4069
+ description: "\u8C03\u7528 /tomatoWorkerController/getFocusStats\u3002\u8FD4\u56DE { sessions, total_sec, total_hours, by_task }\u3002",
4070
+ http: { method: "POST", path: "/tomatoWorkerController/getFocusStats" },
4071
+ params: [
4072
+ { name: "start_time", backendName: "startTime", type: "datetime", transform: "isoToBackendDateTime", description: "\u8D77\u59CB\u65F6\u95F4(ISO,\u53EF\u9009)\u3002\u4E0D\u4F20\u5219\u4ECA\u5929 00:00:00\u3002" },
4073
+ { name: "end_time", backendName: "endTime", type: "datetime", transform: "isoToBackendDateTime", description: "\u622A\u6B62\u65F6\u95F4(ISO,\u53EF\u9009)\u3002\u4E0D\u4F20\u5219\u4ECA\u5929 23:59:59\u3002" }
4074
+ ],
4075
+ output: { shape: "object" },
4076
+ scopes: ["read"],
4077
+ readOnly: true,
4078
+ idempotent: true,
4079
+ cli: { group: "pomo", command: "focus-stats" },
4080
+ tool: { readOnlyHint: true, idempotentHint: true }
4081
+ },
4064
4082
  {
4065
4083
  id: "pomo.sync-pull-worker",
4066
4084
  domain: "pomo",
@@ -4200,6 +4218,71 @@ var projectCapabilities = [
4200
4218
  cli: { group: "project", command: "list" },
4201
4219
  tool: { readOnlyHint: true, idempotentHint: true }
4202
4220
  },
4221
+ {
4222
+ id: "project.list-active",
4223
+ domain: "project",
4224
+ action: "list-active",
4225
+ summary: "\u5217\u51FA\u6D3B\u8DC3\u9879\u76EE(\u672A\u5B8C\u6210\u3001\u672A\u53D6\u6D88\u3001\u672A\u6A21\u677F)\u3002",
4226
+ description: "\u8C03\u7528 /projectController/getActiveProjects\u3002",
4227
+ http: { method: "POST", path: "/projectController/getActiveProjects" },
4228
+ params: [],
4229
+ output: { shape: "array" },
4230
+ scopes: ["read"],
4231
+ readOnly: true,
4232
+ idempotent: true,
4233
+ cli: { group: "project", command: "list-active" },
4234
+ tool: { readOnlyHint: true, idempotentHint: true }
4235
+ },
4236
+ {
4237
+ id: "project.list-archived",
4238
+ domain: "project",
4239
+ action: "list-archived",
4240
+ summary: "\u5217\u51FA\u5DF2\u5F52\u6863/\u5DF2\u5B8C\u6210/\u5DF2\u53D6\u6D88\u7684\u9879\u76EE\u3002",
4241
+ description: "\u8C03\u7528 /projectController/getArchivedProjects\u3002projectState in (2,3,4)\u3002",
4242
+ http: { method: "POST", path: "/projectController/getArchivedProjects" },
4243
+ params: [],
4244
+ output: { shape: "array" },
4245
+ scopes: ["read"],
4246
+ readOnly: true,
4247
+ idempotent: true,
4248
+ cli: { group: "project", command: "list-archived" },
4249
+ tool: { readOnlyHint: true, idempotentHint: true }
4250
+ },
4251
+ {
4252
+ id: "project.search",
4253
+ domain: "project",
4254
+ action: "search",
4255
+ summary: "\u6309\u5173\u952E\u5B57\u641C\u7D22\u9879\u76EE(projectName / projectDesc)\u3002",
4256
+ description: "\u8C03\u7528 /projectController/searchProjects\u3002",
4257
+ http: { method: "POST", path: "/projectController/searchProjects" },
4258
+ params: [
4259
+ { name: "keyword", backendName: "keyword", type: "string", required: true, description: "\u5173\u952E\u5B57\u3002" },
4260
+ { name: "limit", backendName: "limit", type: "integer", default: 50, description: "\u6700\u591A\u8FD4\u56DE\u591A\u5C11\u6761(\u9ED8\u8BA4 50,\u6700\u5927 500)\u3002" }
4261
+ ],
4262
+ output: { shape: "array" },
4263
+ scopes: ["read"],
4264
+ readOnly: true,
4265
+ idempotent: true,
4266
+ cli: { group: "project", command: "search" },
4267
+ tool: { readOnlyHint: true, idempotentHint: true }
4268
+ },
4269
+ {
4270
+ id: "project.stats",
4271
+ domain: "project",
4272
+ action: "stats",
4273
+ summary: "\u5355\u4E2A\u9879\u76EE\u7684\u7EDF\u8BA1\u6570\u636E\u3002",
4274
+ description: "\u8C03\u7528 /projectController/getProjectStats\u3002\u8FD4\u56DE { task_count, done_task_count, progress, exec_time_ms, state }\u3002",
4275
+ http: { method: "POST", path: "/projectController/getProjectStats" },
4276
+ params: [
4277
+ { name: "project_key", backendName: "projectKey", type: "integer", required: true, description: "\u9879\u76EE projectKey\u3002" }
4278
+ ],
4279
+ output: { shape: "object" },
4280
+ scopes: ["read"],
4281
+ readOnly: true,
4282
+ idempotent: true,
4283
+ cli: { group: "project", command: "stats" },
4284
+ tool: { readOnlyHint: true, idempotentHint: true }
4285
+ },
4203
4286
  {
4204
4287
  id: "project.sync-pull",
4205
4288
  domain: "project",
@@ -4741,15 +4824,11 @@ var taskCapabilities = [
4741
4824
  id: "task.completed-today",
4742
4825
  domain: "task",
4743
4826
  action: "completed-today",
4744
- summary: "\u5217\u51FA\u4ECA\u65E5\u5B8C\u6210\u7684\u4EFB\u52A1\u3002",
4745
- description: "\u8C03\u7528 /taskController/getCompletedTasks\u3002\u8FC7\u6EE4\u6761\u4EF6:syncFlag != D\u3001taskState = 0\u3001taskCompletedTime = today\u3002",
4827
+ summary: "\u5217\u51FA\u4ECA\u65E5\uFF08\u6216\u6307\u5B9A\u65E5\u671F\uFF09\u5B8C\u6210\u7684\u4EFB\u52A1\u3002",
4828
+ description: "\u8C03\u7528 /taskController/getCompletedTasks\u3002\u670D\u52A1\u7AEF\u6839\u636E usrKey + date \u76F4\u63A5\u8FC7\u6EE4,\u4E0D\u7528\u5728\u5BA2\u6237\u7AEF\u518D\u505A\u4E00\u6B21\u3002",
4746
4829
  http: { method: "POST", path: "/taskController/getCompletedTasks" },
4747
4830
  params: [
4748
- { name: "is_templete", backendName: "isTemplete", type: "boolean", default: false, transform: "booleanToString", description: "\u6392\u9664\u6A21\u677F\u3002" },
4749
- { name: "sync_flag", backendName: "syncFlag", type: "string", default: "!=D", description: "\u540C\u6B65\u6807\u8BB0\u8FC7\u6EE4\u3002" },
4750
- { name: "task_state", backendName: "taskState", type: "string", default: "=0", description: "\u5DF2\u5B8C\u6210\u3002" },
4751
- { name: "task_completed_time", backendName: "taskCompletedTime", type: "string", default: "=today", description: "\u5B8C\u6210\u65F6\u95F4=\u4ECA\u65E5\u3002" },
4752
- { name: "task_create_time_not_null", backendName: "taskCreateTimeNotNull", type: "boolean", default: true, transform: "booleanToString", description: "\u8981\u6C42 createTime \u975E\u7A7A\u3002" }
4831
+ { name: "date", backendName: "date", type: "date", transform: "isoToBackendDate", description: "\u6307\u5B9A\u65E5\u671F(ISO,\u53EF\u9009)\u3002\u4E0D\u4F20\u5219\u4F7F\u7528\u670D\u52A1\u5668\u4ECA\u5929\u3002" }
4753
4832
  ],
4754
4833
  output: { shape: "array" },
4755
4834
  scopes: ["read"],
@@ -4763,16 +4842,9 @@ var taskCapabilities = [
4763
4842
  domain: "task",
4764
4843
  action: "mit-list",
4765
4844
  summary: "\u5217\u51FA\u4ECA\u65E5 MIT(\u6700\u91CD\u8981)\u4EFB\u52A1\u3002",
4766
- description: "\u8C03\u7528 /taskController/getMitTasks\u3002\u8FC7\u6EE4\u6761\u4EF6\u4E0E PC \u7AEF loadMitHeaderDatas() \u4E00\u81F4\u3002",
4845
+ description: "\u8C03\u7528 /taskController/getMitTasks\u3002\u670D\u52A1\u7AEF\u6309 usrKey \u8FC7\u6EE4 isMIT=true + \u672A\u5B8C\u6210 + taskCreateTime<=\u4ECA\u5929\u3002",
4767
4846
  http: { method: "POST", path: "/taskController/getMitTasks" },
4768
- params: [
4769
- { name: "sync_flag", backendName: "syncFlag", type: "string", default: "!=D", description: "\u540C\u6B65\u6807\u8BB0\u8FC7\u6EE4\u3002" },
4770
- { name: "is_templete", backendName: "isTemplete", type: "boolean", default: false, transform: "booleanToString", description: "\u6392\u9664\u6A21\u677F\u3002" },
4771
- { name: "task_state", backendName: "taskState", type: "string", default: "!=0", description: "\u672A\u5B8C\u6210\u3002" },
4772
- { name: "task_create_time_not_null", backendName: "taskCreateTimeNotNull", type: "boolean", default: true, transform: "booleanToString", description: "\u8981\u6C42 createTime \u975E\u7A7A\u3002" },
4773
- { name: "task_create_time", backendName: "taskCreateTime", type: "string", default: "<=today", description: "\u5230\u4ECA\u65E5\u4E3A\u6B62\u3002" },
4774
- { name: "is_mit", backendName: "isMIT", type: "boolean", default: true, transform: "booleanToString", description: "MIT \u8FC7\u6EE4\u3002" }
4775
- ],
4847
+ params: [],
4776
4848
  output: { shape: "array" },
4777
4849
  scopes: ["read"],
4778
4850
  readOnly: true,
@@ -4785,16 +4857,11 @@ var taskCapabilities = [
4785
4857
  domain: "task",
4786
4858
  action: "calendar",
4787
4859
  summary: "\u6309\u65E5\u671F\u8303\u56F4\u5217\u51FA\u65E5\u5386\u89C6\u56FE\u4EFB\u52A1\u3002",
4788
- description: "\u8C03\u7528 /taskController/getCalendarTaskByDate\u3002\u8FC7\u6EE4\u4E0E\u5B89\u5353\u7AEF\u4E00\u81F4(syncFlag!=D\u3001taskState!=0\u3001isTemplete=false\u3001taskStartItem!=FT\u3001taskStartItem!=\u5783\u573E\u7BB1)\u3002",
4860
+ description: "\u8C03\u7528 /taskController/getCalendarTaskByDate\u3002\u670D\u52A1\u7AEF\u5DF2\u5185\u7F6E\u8FC7\u6EE4(\u672A\u5B8C\u6210 + \u975E\u6A21\u677F + \u975E\u5783\u573E\u7BB1)\u3002",
4789
4861
  http: { method: "POST", path: "/taskController/getCalendarTaskByDate" },
4790
4862
  params: [
4791
4863
  { name: "start_date", backendName: "startDate", type: "date", transform: "isoToBackendDate", required: true, description: "\u8303\u56F4\u8D77\u59CB(ISO \u65E5\u671F)\u3002" },
4792
- { name: "end_date", backendName: "endDate", type: "date", transform: "isoToBackendDate", required: true, description: "\u8303\u56F4\u622A\u6B62(ISO \u65E5\u671F)\u3002" },
4793
- { name: "sync_flag", backendName: "syncFlag", type: "string", default: "!=D", description: "\u540C\u6B65\u6807\u8BB0\u8FC7\u6EE4\u3002" },
4794
- { name: "task_state", backendName: "taskState", type: "string", default: "!=0", description: "\u672A\u5B8C\u6210\u3002" },
4795
- { name: "is_templete", backendName: "isTemplete", type: "boolean", default: false, transform: "booleanToString", description: "\u6392\u9664\u6A21\u677F\u3002" },
4796
- { name: "task_start_item_not_1", backendName: "taskStartItemNot1", type: "string", default: "FT", description: "\u6392\u9664 FT \u9879\u3002" },
4797
- { name: "task_start_item_not_2", backendName: "taskStartItemNot2", type: "string", default: "\u5783\u573E\u7BB1", description: "\u6392\u9664\u5783\u573E\u7BB1\u3002" }
4864
+ { name: "end_date", backendName: "endDate", type: "date", transform: "isoToBackendDate", required: true, description: "\u8303\u56F4\u622A\u6B62(ISO \u65E5\u671F)\u3002" }
4798
4865
  ],
4799
4866
  output: { shape: "array" },
4800
4867
  scopes: ["read"],
@@ -4803,6 +4870,72 @@ var taskCapabilities = [
4803
4870
  cli: { group: "task", command: "calendar" },
4804
4871
  tool: { readOnlyHint: true, idempotentHint: true }
4805
4872
  },
4873
+ {
4874
+ id: "task.overdue",
4875
+ domain: "task",
4876
+ action: "overdue",
4877
+ summary: "\u5217\u51FA\u5DF2\u8FC7\u671F\u672A\u5B8C\u6210\u7684\u4EFB\u52A1(taskCreateTime < \u4ECA\u5929)\u3002",
4878
+ description: "\u8C03\u7528 /taskController/getOverdueTasks\u3002",
4879
+ http: { method: "POST", path: "/taskController/getOverdueTasks" },
4880
+ params: [],
4881
+ output: { shape: "array" },
4882
+ scopes: ["read"],
4883
+ readOnly: true,
4884
+ idempotent: true,
4885
+ cli: { group: "task", command: "overdue" },
4886
+ tool: { readOnlyHint: true, idempotentHint: true }
4887
+ },
4888
+ {
4889
+ id: "task.inbox",
4890
+ domain: "task",
4891
+ action: "inbox",
4892
+ summary: "\u5217\u51FA\u6536\u96C6\u7BB1\u4EFB\u52A1(\u672A\u5B89\u6392\u65F6\u95F4\u7684\u672A\u5B8C\u6210\u4EFB\u52A1)\u3002",
4893
+ description: "\u8C03\u7528 /taskController/getInboxTasks\u3002",
4894
+ http: { method: "POST", path: "/taskController/getInboxTasks" },
4895
+ params: [],
4896
+ output: { shape: "array" },
4897
+ scopes: ["read"],
4898
+ readOnly: true,
4899
+ idempotent: true,
4900
+ cli: { group: "task", command: "inbox" },
4901
+ tool: { readOnlyHint: true, idempotentHint: true }
4902
+ },
4903
+ {
4904
+ id: "task.search",
4905
+ domain: "task",
4906
+ action: "search",
4907
+ summary: "\u6309\u5173\u952E\u5B57\u641C\u7D22\u4EFB\u52A1(taskName / taskDesc)\u3002",
4908
+ description: "\u8C03\u7528 /taskController/searchTasks\u3002\u670D\u52A1\u7AEF\u6309 LIKE \u5339\u914D\u5E76\u6309 latestVersion \u5012\u5E8F\u8FD4\u56DE\u3002",
4909
+ http: { method: "POST", path: "/taskController/searchTasks" },
4910
+ params: [
4911
+ { name: "keyword", backendName: "keyword", type: "string", required: true, description: "\u5173\u952E\u5B57\u3002" },
4912
+ { name: "limit", backendName: "limit", type: "integer", default: 50, description: "\u6700\u591A\u8FD4\u56DE\u591A\u5C11\u6761(\u9ED8\u8BA4 50,\u6700\u5927 500)\u3002" }
4913
+ ],
4914
+ output: { shape: "array" },
4915
+ scopes: ["read"],
4916
+ readOnly: true,
4917
+ idempotent: true,
4918
+ cli: { group: "task", command: "search" },
4919
+ tool: { readOnlyHint: true, idempotentHint: true }
4920
+ },
4921
+ {
4922
+ id: "task.stats",
4923
+ domain: "task",
4924
+ action: "stats",
4925
+ summary: "\u4EFB\u52A1\u5B8C\u6210\u60C5\u51B5\u7EDF\u8BA1(\u6307\u5B9A\u65F6\u95F4\u7A97)\u3002",
4926
+ description: "\u8C03\u7528 /taskController/getTaskStats\u3002\u8FD4\u56DE { created, completed, completion_rate, by_project }\u3002",
4927
+ http: { method: "POST", path: "/taskController/getTaskStats" },
4928
+ params: [
4929
+ { name: "start_date", backendName: "startDate", type: "date", transform: "isoToBackendDate", description: "\u8D77\u59CB\u65E5\u671F(ISO,\u53EF\u9009)\u3002\u4E0D\u4F20\u5219\u4ECA\u5929\u3002" },
4930
+ { name: "end_date", backendName: "endDate", type: "date", transform: "isoToBackendDate", description: "\u622A\u6B62\u65E5\u671F(ISO,\u53EF\u9009)\u3002\u4E0D\u4F20\u5219\u4ECA\u5929\u3002" }
4931
+ ],
4932
+ output: { shape: "object" },
4933
+ scopes: ["read"],
4934
+ readOnly: true,
4935
+ idempotent: true,
4936
+ cli: { group: "task", command: "stats" },
4937
+ tool: { readOnlyHint: true, idempotentHint: true }
4938
+ },
4806
4939
  {
4807
4940
  id: "task.move",
4808
4941
  domain: "task",
@@ -8010,7 +8143,7 @@ function describeGroup(name) {
8010
8143
  }
8011
8144
 
8012
8145
  // src/program.ts
8013
- var CLI_VERSION = true ? "0.1.6" : "0.0.0";
8146
+ var CLI_VERSION = true ? "0.1.8" : "0.0.0";
8014
8147
  function buildProgram() {
8015
8148
  const program3 = new Command();
8016
8149
  program3.name("zentodo").description("ZenTodo \u547D\u4EE4\u884C\u5DE5\u5177 \u2014 \u57FA\u4E8E\u6E05\u5355\u9A71\u52A8,\u8FDE\u63A5 ZenTodo \u540E\u7AEF\u3002\u6240\u6709\u8BF7\u6C42\u4F7F\u7528 FormData\u3002").version(CLI_VERSION, "-V, --version", "\u6253\u5370 CLI \u7248\u672C").helpOption("-h, --help", "\u663E\u793A\u5E2E\u52A9\u4FE1\u606F").addHelpCommand("help [command]", "\u67E5\u770B\u547D\u4EE4\u5E2E\u52A9").option("--profile <name>", "\u4F7F\u7528\u6307\u5B9A Profile(\u9ED8\u8BA4\u4F7F\u7528 current_profile)").option("--server <url>", "\u8986\u76D6\u540E\u7AEF\u5730\u5740").option("--token <token>", "\u8986\u76D6\u672C\u5730 Token").option("--log-level <level>", "\u65E5\u5FD7\u7EA7\u522B:trace|debug|info|warn|error", "info").option("--log-file <path>", "\u8FFD\u52A0\u65E5\u5FD7\u5230\u6307\u5B9A\u6587\u4EF6").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").option("--no-color", "\u5173\u95ED\u5F69\u8272\u8F93\u51FA").option("--dry-run", "\u53EA\u6253\u5370\u5C06\u53D1\u9001\u7684\u8BF7\u6C42,\u4E0D\u771F\u6B63\u8C03\u7528\u540E\u7AEF").option("--yes", "\u8DF3\u8FC7\u7834\u574F\u6027\u64CD\u4F5C\u7684\u786E\u8BA4\u63D0\u793A").option("--local", "\u4F18\u5148\u4F7F\u7528\u672C\u5730 SQLite(\u82E5\u53EF\u7528)").option("--remote", "\u5F3A\u5236\u4F7F\u7528\u8FDC\u7A0B HTTP \u6A21\u5F0F").option("--json", "JSON \u8F93\u51FA").option("--ndjson", "\u6309\u884C\u8F93\u51FA JSON(\u9002\u5408\u6D41\u5F0F\u5904\u7406)").option("--yaml", "YAML \u8F93\u51FA").option("--quiet", "\u9690\u85CF\u975E\u5FC5\u8981\u8F93\u51FA");
@@ -93,6 +93,16 @@ curl -X POST http://ztdfwq.qmlist.net:8082/zentodoserver/projectController/getAl
93
93
 
94
94
  如果 `zentodo` 命令不可用,先按"前置条件"安装,不要绕过 CLI 直接调接口。
95
95
 
96
+ **关于 "Session 过期 / 302 重定向"的常见误解:**
97
+
98
+ ZenTodo 后端使用 Spring Security + Session Cookie 认证。CLI 是无状态 HTTP 调用,不带 Cookie。
99
+ 大部分接口(以 `usrKey` 参数形式设计)对 CLI 完全可用;**极少数旧接口依赖 Session,CLI 调它们会被 302 重定向到 `/login`**。
100
+
101
+ 遇到这种情况:
102
+ - **不要**提示用户"session 过期,请重新登录"——CLI 本来就不走 session
103
+ - 应该选用替代接口(几乎每种查询都有 `usrKey` 版本)
104
+ - 或者让用户反馈,由后端把该接口改造成 FormData 传 `usrKey` 模式
105
+
96
106
  ---
97
107
 
98
108
 
@@ -531,6 +531,19 @@ zentodo auth login-email --email a@b.com
531
531
  - **所需 scope**:`read`
532
532
  - **对应 Skill 工具**:`zentodo.pomo.history`
533
533
 
534
+ ### `zentodo pomo focus-stats` _(只读 / 幂等)_
535
+
536
+ 专注时长统计(时间窗)。
537
+
538
+ - **后端端点**:`POST /tomatoWorkerController/getFocusStats`
539
+ - **所需 scope**:`read`
540
+ - **对应 Skill 工具**:`zentodo.pomo.focus-stats`
541
+
542
+ | 参数 | 类型 | 必填 | 说明 |
543
+ | --- | --- | --- | --- |
544
+ | `start_time` | datetime | 否 | 起始时间(ISO,可选)。不传则今天 00:00:00。 |
545
+ | `end_time` | datetime | 否 | 截止时间(ISO,可选)。不传则今天 23:59:59。 |
546
+
534
547
  ### `zentodo pomo sync-pull-worker` _(只读)_
535
548
 
536
549
  按 clientVersion 拉取番茄钟记录增量。
@@ -623,6 +636,47 @@ zentodo auth login-email --email a@b.com
623
636
  - **所需 scope**:`read`
624
637
  - **对应 Skill 工具**:`zentodo.project.list-all`
625
638
 
639
+ ### `zentodo project list-active` _(只读 / 幂等)_
640
+
641
+ 列出活跃项目(未完成、未取消、未模板)。
642
+
643
+ - **后端端点**:`POST /projectController/getActiveProjects`
644
+ - **所需 scope**:`read`
645
+ - **对应 Skill 工具**:`zentodo.project.list-active`
646
+
647
+ ### `zentodo project list-archived` _(只读 / 幂等)_
648
+
649
+ 列出已归档/已完成/已取消的项目。
650
+
651
+ - **后端端点**:`POST /projectController/getArchivedProjects`
652
+ - **所需 scope**:`read`
653
+ - **对应 Skill 工具**:`zentodo.project.list-archived`
654
+
655
+ ### `zentodo project search` _(只读 / 幂等)_
656
+
657
+ 按关键字搜索项目(projectName / projectDesc)。
658
+
659
+ - **后端端点**:`POST /projectController/searchProjects`
660
+ - **所需 scope**:`read`
661
+ - **对应 Skill 工具**:`zentodo.project.search`
662
+
663
+ | 参数 | 类型 | 必填 | 说明 |
664
+ | --- | --- | --- | --- |
665
+ | `keyword` | string | 是 | 关键字。 |
666
+ | `limit` | integer | 否 | 最多返回多少条(默认 50,最大 500)。 |
667
+
668
+ ### `zentodo project stats` _(只读 / 幂等)_
669
+
670
+ 单个项目的统计数据。
671
+
672
+ - **后端端点**:`POST /projectController/getProjectStats`
673
+ - **所需 scope**:`read`
674
+ - **对应 Skill 工具**:`zentodo.project.stats`
675
+
676
+ | 参数 | 类型 | 必填 | 说明 |
677
+ | --- | --- | --- | --- |
678
+ | `project_key` | integer | 是 | 项目 projectKey。 |
679
+
626
680
  ### `zentodo project sync-pull` _(只读)_
627
681
 
628
682
  按 clientVersion 拉取项目增量。
@@ -1048,7 +1102,7 @@ zentodo task add --title "写周报" --due 2025-09-05T14:00 --priority 3
1048
1102
 
1049
1103
  ### `zentodo task completed-today` _(只读 / 幂等)_
1050
1104
 
1051
- 列出今日完成的任务。
1105
+ 列出今日(或指定日期)完成的任务。
1052
1106
 
1053
1107
  - **后端端点**:`POST /taskController/getCompletedTasks`
1054
1108
  - **所需 scope**:`read`
@@ -1056,11 +1110,7 @@ zentodo task add --title "写周报" --due 2025-09-05T14:00 --priority 3
1056
1110
 
1057
1111
  | 参数 | 类型 | 必填 | 说明 |
1058
1112
  | --- | --- | --- | --- |
1059
- | `is_templete` | boolean | 否 | 排除模板。 |
1060
- | `sync_flag` | string | 否 | 同步标记过滤。 |
1061
- | `task_state` | string | 否 | 已完成。 |
1062
- | `task_completed_time` | string | 否 | 完成时间=今日。 |
1063
- | `task_create_time_not_null` | boolean | 否 | 要求 createTime 非空。 |
1113
+ | `date` | date | 否 | 指定日期(ISO,可选)。不传则使用服务器今天。 |
1064
1114
 
1065
1115
  ### `zentodo task mit-list` _(只读 / 幂等)_
1066
1116
 
@@ -1070,15 +1120,6 @@ zentodo task add --title "写周报" --due 2025-09-05T14:00 --priority 3
1070
1120
  - **所需 scope**:`read`
1071
1121
  - **对应 Skill 工具**:`zentodo.task.mit-list`
1072
1122
 
1073
- | 参数 | 类型 | 必填 | 说明 |
1074
- | --- | --- | --- | --- |
1075
- | `sync_flag` | string | 否 | 同步标记过滤。 |
1076
- | `is_templete` | boolean | 否 | 排除模板。 |
1077
- | `task_state` | string | 否 | 未完成。 |
1078
- | `task_create_time_not_null` | boolean | 否 | 要求 createTime 非空。 |
1079
- | `task_create_time` | string | 否 | 到今日为止。 |
1080
- | `is_mit` | boolean | 否 | MIT 过滤。 |
1081
-
1082
1123
  ### `zentodo task calendar` _(只读 / 幂等)_
1083
1124
 
1084
1125
  按日期范围列出日历视图任务。
@@ -1091,11 +1132,48 @@ zentodo task add --title "写周报" --due 2025-09-05T14:00 --priority 3
1091
1132
  | --- | --- | --- | --- |
1092
1133
  | `start_date` | date | 是 | 范围起始(ISO 日期)。 |
1093
1134
  | `end_date` | date | 是 | 范围截止(ISO 日期)。 |
1094
- | `sync_flag` | string | 否 | 同步标记过滤。 |
1095
- | `task_state` | string | | 未完成。 |
1096
- | `is_templete` | boolean | 否 | 排除模板。 |
1097
- | `task_start_item_not_1` | string | 否 | 排除 FT 项。 |
1098
- | `task_start_item_not_2` | string | 否 | 排除垃圾箱。 |
1135
+
1136
+ ### `zentodo task overdue` _(只读 / 幂等)_
1137
+
1138
+ 列出已过期未完成的任务(taskCreateTime < 今天)。
1139
+
1140
+ - **后端端点**:`POST /taskController/getOverdueTasks`
1141
+ - **所需 scope**:`read`
1142
+ - **对应 Skill 工具**:`zentodo.task.overdue`
1143
+
1144
+ ### `zentodo task inbox` _(只读 / 幂等)_
1145
+
1146
+ 列出收集箱任务(未安排时间的未完成任务)。
1147
+
1148
+ - **后端端点**:`POST /taskController/getInboxTasks`
1149
+ - **所需 scope**:`read`
1150
+ - **对应 Skill 工具**:`zentodo.task.inbox`
1151
+
1152
+ ### `zentodo task search` _(只读 / 幂等)_
1153
+
1154
+ 按关键字搜索任务(taskName / taskDesc)。
1155
+
1156
+ - **后端端点**:`POST /taskController/searchTasks`
1157
+ - **所需 scope**:`read`
1158
+ - **对应 Skill 工具**:`zentodo.task.search`
1159
+
1160
+ | 参数 | 类型 | 必填 | 说明 |
1161
+ | --- | --- | --- | --- |
1162
+ | `keyword` | string | 是 | 关键字。 |
1163
+ | `limit` | integer | 否 | 最多返回多少条(默认 50,最大 500)。 |
1164
+
1165
+ ### `zentodo task stats` _(只读 / 幂等)_
1166
+
1167
+ 任务完成情况统计(指定时间窗)。
1168
+
1169
+ - **后端端点**:`POST /taskController/getTaskStats`
1170
+ - **所需 scope**:`read`
1171
+ - **对应 Skill 工具**:`zentodo.task.stats`
1172
+
1173
+ | 参数 | 类型 | 必填 | 说明 |
1174
+ | --- | --- | --- | --- |
1175
+ | `start_date` | date | 否 | 起始日期(ISO,可选)。不传则今天。 |
1176
+ | `end_date` | date | 否 | 截止日期(ISO,可选)。不传则今天。 |
1099
1177
 
1100
1178
  ### `zentodo task move`
1101
1179
 
@@ -29,6 +29,10 @@
29
29
  | task | `zentodo task completed-today` | `zentodo.task.completed-today` | `POST /taskController/getCompletedTasks` | read |
30
30
  | task | `zentodo task mit-list` | `zentodo.task.mit-list` | `POST /taskController/getMitTasks` | read |
31
31
  | task | `zentodo task calendar` | `zentodo.task.calendar` | `POST /taskController/getCalendarTaskByDate` | read |
32
+ | task | `zentodo task overdue` | `zentodo.task.overdue` | `POST /taskController/getOverdueTasks` | read |
33
+ | task | `zentodo task inbox` | `zentodo.task.inbox` | `POST /taskController/getInboxTasks` | read |
34
+ | task | `zentodo task search` | `zentodo.task.search` | `POST /taskController/searchTasks` | read |
35
+ | task | `zentodo task stats` | `zentodo.task.stats` | `POST /taskController/getTaskStats` | read |
32
36
  | task | `zentodo task move` | `zentodo.task.move` | `POST /taskController/updateTaskCreateTime` | write |
33
37
  | task | `zentodo task sync-pull` | `zentodo.task.sync-pull` | `POST /taskController/getSyncTaskList` | sync, read |
34
38
  | task | `zentodo task sync-push` | `zentodo.task.sync-push` | `POST /taskController/putSyncTask` | sync, write |
@@ -38,6 +42,10 @@
38
42
  | subtask | `zentodo subtask sync-pull` | `zentodo.subtask.sync-pull` | `POST /subTaskController/getSyncSubTaskList` | sync, read |
39
43
  | project | `zentodo project upsert` | `zentodo.project.sync-push` | `POST /projectController/putSyncProject` | sync, write |
40
44
  | project | `zentodo project list` | `zentodo.project.list-all` | `POST /projectController/getAllProjectByUserId` | read |
45
+ | project | `zentodo project list-active` | `zentodo.project.list-active` | `POST /projectController/getActiveProjects` | read |
46
+ | project | `zentodo project list-archived` | `zentodo.project.list-archived` | `POST /projectController/getArchivedProjects` | read |
47
+ | project | `zentodo project search` | `zentodo.project.search` | `POST /projectController/searchProjects` | read |
48
+ | project | `zentodo project stats` | `zentodo.project.stats` | `POST /projectController/getProjectStats` | read |
41
49
  | project | `zentodo project sync-pull` | `zentodo.project.sync-pull` | `POST /projectController/getSyncProjectList` | sync, read |
42
50
  | subproject | `zentodo subproject upsert` | `zentodo.subproject.sync-push` | `POST /subProjectController/putSyncSubProject` | sync, write |
43
51
  | subproject | `zentodo subproject list` | `zentodo.subproject.list-all` | `POST /subProjectController/getAllSubProjectByUserId` | read |
@@ -69,6 +77,7 @@
69
77
  | pomo | `zentodo pomo start` | `zentodo.pomo.start` | `POST /timerController/startPomodoro` | write |
70
78
  | pomo | `zentodo pomo stop` | `zentodo.pomo.stop` | `POST /timerController/stopTimer` | write |
71
79
  | pomo | `zentodo pomo history` | `zentodo.pomo.history` | `POST /tomatoWorkerController/getAllTomatoByUserId` | read |
80
+ | pomo | `zentodo pomo focus-stats` | `zentodo.pomo.focus-stats` | `POST /tomatoWorkerController/getFocusStats` | read |
72
81
  | pomo | `zentodo pomo sync-pull-worker` | `zentodo.pomo.sync-pull-worker` | `POST /tomatoWorkerController/getSyncTomatoWorkerList` | sync, read |
73
82
  | pomo | `zentodo pomo sync-push-worker` | `zentodo.pomo.sync-push-worker` | `POST /tomatoWorkerController/putSyncTomatoWorker` | sync, write |
74
83
  | pomo | `zentodo pomo config-get` | `zentodo.pomo.config-get` | `POST /tomatoConfigController/getAllTomatoConfigByUserId` | read |