@jackwener/opencli 1.5.5 → 1.5.7

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 (540) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +31 -4
  3. package/README.zh-CN.md +40 -5
  4. package/SKILL.md +1 -1
  5. package/dist/browser/cdp.d.ts +1 -0
  6. package/dist/browser/cdp.js +30 -27
  7. package/dist/browser/daemon-client.d.ts +11 -1
  8. package/dist/browser/daemon-client.js +3 -0
  9. package/dist/browser/dom-helpers.js +1 -0
  10. package/dist/browser/dom-helpers.test.js +14 -1
  11. package/dist/browser/mcp.js +18 -13
  12. package/dist/browser/page.d.ts +6 -0
  13. package/dist/browser/page.js +37 -2
  14. package/dist/browser/page.test.d.ts +1 -0
  15. package/dist/browser/page.test.js +44 -0
  16. package/dist/browser/stealth.js +198 -0
  17. package/dist/browser/stealth.test.d.ts +1 -0
  18. package/dist/browser/stealth.test.js +134 -0
  19. package/dist/browser.test.js +1 -1
  20. package/dist/build-manifest.d.ts +1 -0
  21. package/dist/build-manifest.js +5 -1
  22. package/dist/build-manifest.test.js +2 -0
  23. package/dist/cli-manifest.json +1821 -252
  24. package/dist/cli.js +20 -3
  25. package/dist/clis/antigravity/serve.d.ts +1 -1
  26. package/dist/clis/antigravity/serve.js +5 -8
  27. package/dist/clis/band/bands.d.ts +1 -0
  28. package/dist/clis/band/bands.js +72 -0
  29. package/dist/clis/band/mentions.d.ts +1 -0
  30. package/dist/clis/band/mentions.js +127 -0
  31. package/dist/clis/band/post.d.ts +1 -0
  32. package/dist/clis/band/post.js +175 -0
  33. package/dist/clis/band/posts.d.ts +1 -0
  34. package/dist/clis/band/posts.js +94 -0
  35. package/dist/clis/bilibili/subtitle.js +4 -0
  36. package/dist/clis/bilibili/subtitle.test.d.ts +1 -0
  37. package/dist/clis/bilibili/subtitle.test.js +48 -0
  38. package/dist/clis/chatwise/ask.js +0 -2
  39. package/dist/clis/chatwise/export.js +0 -2
  40. package/dist/clis/chatwise/history.js +0 -2
  41. package/dist/clis/chatwise/model.js +0 -2
  42. package/dist/clis/chatwise/new.js +1 -2
  43. package/dist/clis/chatwise/read.js +0 -2
  44. package/dist/clis/chatwise/screenshot.js +1 -2
  45. package/dist/clis/chatwise/send.js +0 -2
  46. package/dist/clis/chatwise/status.js +1 -2
  47. package/dist/clis/ctrip/search.d.ts +13 -0
  48. package/dist/clis/ctrip/search.js +73 -48
  49. package/dist/clis/ctrip/search.test.d.ts +1 -0
  50. package/dist/clis/ctrip/search.test.js +64 -0
  51. package/dist/clis/doubao/detail.d.ts +1 -0
  52. package/dist/clis/doubao/detail.js +33 -0
  53. package/dist/clis/doubao/detail.test.d.ts +1 -0
  54. package/dist/clis/doubao/detail.test.js +42 -0
  55. package/dist/clis/doubao/history.d.ts +1 -0
  56. package/dist/clis/doubao/history.js +28 -0
  57. package/dist/clis/doubao/history.test.d.ts +1 -0
  58. package/dist/clis/doubao/history.test.js +37 -0
  59. package/dist/clis/doubao/meeting-summary.d.ts +1 -0
  60. package/dist/clis/doubao/meeting-summary.js +39 -0
  61. package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
  62. package/dist/clis/doubao/meeting-transcript.js +36 -0
  63. package/dist/clis/doubao/utils.d.ts +27 -0
  64. package/dist/clis/doubao/utils.js +317 -0
  65. package/dist/clis/doubao/utils.test.d.ts +1 -0
  66. package/dist/clis/doubao/utils.test.js +24 -0
  67. package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
  68. package/dist/clis/douyin/_shared/public-api.js +29 -0
  69. package/dist/clis/douyin/_shared/sts2.js +8 -2
  70. package/dist/clis/douyin/_shared/sts2.test.d.ts +1 -0
  71. package/dist/clis/douyin/_shared/sts2.test.js +27 -0
  72. package/dist/clis/douyin/activities.js +4 -2
  73. package/dist/clis/douyin/activities.test.js +34 -1
  74. package/dist/clis/douyin/collections.js +1 -1
  75. package/dist/clis/douyin/collections.test.js +24 -2
  76. package/dist/clis/douyin/draft.d.ts +8 -11
  77. package/dist/clis/douyin/draft.js +302 -185
  78. package/dist/clis/douyin/draft.test.d.ts +1 -1
  79. package/dist/clis/douyin/draft.test.js +357 -2
  80. package/dist/clis/douyin/hashtag.js +9 -2
  81. package/dist/clis/douyin/hashtag.test.js +35 -2
  82. package/dist/clis/douyin/profile.js +1 -1
  83. package/dist/clis/douyin/profile.test.js +36 -1
  84. package/dist/clis/douyin/user-videos.d.ts +5 -0
  85. package/dist/clis/douyin/user-videos.js +74 -0
  86. package/dist/clis/douyin/user-videos.test.d.ts +1 -0
  87. package/dist/clis/douyin/user-videos.test.js +108 -0
  88. package/dist/clis/douyin/videos.js +22 -5
  89. package/dist/clis/douyin/videos.test.js +45 -2
  90. package/dist/clis/facebook/search.test.d.ts +5 -0
  91. package/dist/clis/facebook/search.test.js +60 -0
  92. package/dist/clis/facebook/search.yaml +4 -3
  93. package/dist/clis/instagram/download.d.ts +16 -0
  94. package/dist/clis/instagram/download.js +225 -0
  95. package/dist/clis/instagram/download.test.d.ts +1 -0
  96. package/dist/clis/instagram/download.test.js +118 -0
  97. package/dist/clis/notebooklm/bind-current.d.ts +1 -0
  98. package/dist/clis/notebooklm/bind-current.js +29 -0
  99. package/dist/clis/notebooklm/bind-current.test.d.ts +1 -0
  100. package/dist/clis/notebooklm/bind-current.test.js +35 -0
  101. package/dist/clis/notebooklm/binding.test.d.ts +1 -0
  102. package/dist/clis/notebooklm/binding.test.js +44 -0
  103. package/dist/clis/notebooklm/compat.test.d.ts +3 -0
  104. package/dist/clis/notebooklm/compat.test.js +16 -0
  105. package/dist/clis/notebooklm/current.d.ts +1 -0
  106. package/dist/clis/notebooklm/current.js +28 -0
  107. package/dist/clis/notebooklm/get.d.ts +1 -0
  108. package/dist/clis/notebooklm/get.js +37 -0
  109. package/dist/clis/notebooklm/history.d.ts +1 -0
  110. package/dist/clis/notebooklm/history.js +25 -0
  111. package/dist/clis/notebooklm/history.test.d.ts +1 -0
  112. package/dist/clis/notebooklm/history.test.js +58 -0
  113. package/dist/clis/notebooklm/list.d.ts +1 -0
  114. package/dist/clis/notebooklm/list.js +35 -0
  115. package/dist/clis/notebooklm/note-list.d.ts +1 -0
  116. package/dist/clis/notebooklm/note-list.js +28 -0
  117. package/dist/clis/notebooklm/note-list.test.d.ts +1 -0
  118. package/dist/clis/notebooklm/note-list.test.js +56 -0
  119. package/dist/clis/notebooklm/notes-get.d.ts +1 -0
  120. package/dist/clis/notebooklm/notes-get.js +47 -0
  121. package/dist/clis/notebooklm/notes-get.test.d.ts +1 -0
  122. package/dist/clis/notebooklm/notes-get.test.js +72 -0
  123. package/dist/clis/notebooklm/rpc.d.ts +36 -0
  124. package/dist/clis/notebooklm/rpc.js +189 -0
  125. package/dist/clis/notebooklm/rpc.test.d.ts +1 -0
  126. package/dist/clis/notebooklm/rpc.test.js +105 -0
  127. package/dist/clis/notebooklm/shared.d.ts +87 -0
  128. package/dist/clis/notebooklm/shared.js +3 -0
  129. package/dist/clis/notebooklm/source-fulltext.d.ts +1 -0
  130. package/dist/clis/notebooklm/source-fulltext.js +44 -0
  131. package/dist/clis/notebooklm/source-fulltext.test.d.ts +1 -0
  132. package/dist/clis/notebooklm/source-fulltext.test.js +106 -0
  133. package/dist/clis/notebooklm/source-get.d.ts +1 -0
  134. package/dist/clis/notebooklm/source-get.js +40 -0
  135. package/dist/clis/notebooklm/source-get.test.d.ts +1 -0
  136. package/dist/clis/notebooklm/source-get.test.js +84 -0
  137. package/dist/clis/notebooklm/source-guide.d.ts +1 -0
  138. package/dist/clis/notebooklm/source-guide.js +44 -0
  139. package/dist/clis/notebooklm/source-guide.test.d.ts +1 -0
  140. package/dist/clis/notebooklm/source-guide.test.js +104 -0
  141. package/dist/clis/notebooklm/source-list.d.ts +1 -0
  142. package/dist/clis/notebooklm/source-list.js +30 -0
  143. package/dist/clis/notebooklm/status.d.ts +1 -0
  144. package/dist/clis/notebooklm/status.js +31 -0
  145. package/dist/clis/notebooklm/summary.d.ts +1 -0
  146. package/dist/clis/notebooklm/summary.js +30 -0
  147. package/dist/clis/notebooklm/summary.test.d.ts +1 -0
  148. package/dist/clis/notebooklm/summary.test.js +78 -0
  149. package/dist/clis/notebooklm/utils.d.ts +37 -0
  150. package/dist/clis/notebooklm/utils.js +739 -0
  151. package/dist/clis/notebooklm/utils.test.d.ts +1 -0
  152. package/dist/clis/notebooklm/utils.test.js +390 -0
  153. package/dist/clis/ones/common.d.ts +32 -0
  154. package/dist/clis/ones/common.js +144 -0
  155. package/dist/clis/ones/enrich-tasks.d.ts +5 -0
  156. package/dist/clis/ones/enrich-tasks.js +37 -0
  157. package/dist/clis/ones/login.d.ts +1 -0
  158. package/dist/clis/ones/login.js +80 -0
  159. package/dist/clis/ones/logout.d.ts +1 -0
  160. package/dist/clis/ones/logout.js +17 -0
  161. package/dist/clis/ones/me.d.ts +1 -0
  162. package/dist/clis/ones/me.js +30 -0
  163. package/dist/clis/ones/my-tasks.d.ts +1 -0
  164. package/dist/clis/ones/my-tasks.js +120 -0
  165. package/dist/clis/ones/resolve-labels.d.ts +10 -0
  166. package/dist/clis/ones/resolve-labels.js +64 -0
  167. package/dist/clis/ones/task-helpers.d.ts +29 -0
  168. package/dist/clis/ones/task-helpers.js +212 -0
  169. package/dist/clis/ones/task-helpers.test.d.ts +1 -0
  170. package/dist/clis/ones/task-helpers.test.js +12 -0
  171. package/dist/clis/ones/task.d.ts +1 -0
  172. package/dist/clis/ones/task.js +66 -0
  173. package/dist/clis/ones/tasks.d.ts +1 -0
  174. package/dist/clis/ones/tasks.js +79 -0
  175. package/dist/clis/ones/token-info.d.ts +1 -0
  176. package/dist/clis/ones/token-info.js +42 -0
  177. package/dist/clis/ones/worklog.d.ts +11 -0
  178. package/dist/clis/ones/worklog.js +267 -0
  179. package/dist/clis/ones/worklog.test.d.ts +1 -0
  180. package/dist/clis/ones/worklog.test.js +20 -0
  181. package/dist/clis/spotify/spotify.d.ts +1 -0
  182. package/dist/clis/spotify/spotify.js +316 -0
  183. package/dist/clis/spotify/utils.d.ts +21 -0
  184. package/dist/clis/spotify/utils.js +66 -0
  185. package/dist/clis/spotify/utils.test.d.ts +1 -0
  186. package/dist/clis/spotify/utils.test.js +67 -0
  187. package/dist/clis/substack/utils.d.ts +4 -0
  188. package/dist/clis/substack/utils.js +8 -2
  189. package/dist/clis/substack/utils.test.d.ts +1 -0
  190. package/dist/clis/substack/utils.test.js +46 -0
  191. package/dist/clis/tieba/commands.test.d.ts +4 -0
  192. package/dist/clis/tieba/commands.test.js +79 -0
  193. package/dist/clis/tieba/hot.d.ts +1 -0
  194. package/dist/clis/tieba/hot.js +48 -0
  195. package/dist/clis/tieba/posts.d.ts +1 -0
  196. package/dist/clis/tieba/posts.js +85 -0
  197. package/dist/clis/tieba/read.d.ts +1 -0
  198. package/dist/clis/tieba/read.js +140 -0
  199. package/dist/clis/tieba/search.d.ts +1 -0
  200. package/dist/clis/tieba/search.js +108 -0
  201. package/dist/clis/tieba/utils.d.ts +101 -0
  202. package/dist/clis/tieba/utils.js +240 -0
  203. package/dist/clis/tieba/utils.test.d.ts +1 -0
  204. package/dist/clis/tieba/utils.test.js +290 -0
  205. package/dist/clis/v2ex/hot.yaml +4 -1
  206. package/dist/clis/v2ex/latest.yaml +4 -1
  207. package/dist/clis/v2ex/topic.yaml +6 -1
  208. package/dist/clis/weixin/download.d.ts +9 -0
  209. package/dist/clis/weixin/download.js +76 -6
  210. package/dist/clis/weread/book.js +206 -13
  211. package/dist/clis/weread/commands.test.js +331 -0
  212. package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
  213. package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
  214. package/dist/clis/weread/search-regression.test.d.ts +1 -0
  215. package/dist/clis/weread/search-regression.test.js +407 -0
  216. package/dist/clis/weread/search.js +143 -7
  217. package/dist/clis/weread/shelf.js +13 -95
  218. package/dist/clis/weread/utils.d.ts +56 -0
  219. package/dist/clis/weread/utils.js +234 -7
  220. package/dist/clis/weread/utils.test.js +71 -1
  221. package/dist/clis/xiaohongshu/comments.d.ts +3 -0
  222. package/dist/clis/xiaohongshu/comments.js +76 -17
  223. package/dist/clis/xiaohongshu/comments.test.js +70 -9
  224. package/dist/clis/xiaohongshu/download.d.ts +4 -1
  225. package/dist/clis/xiaohongshu/download.js +83 -22
  226. package/dist/clis/xiaohongshu/download.test.d.ts +1 -0
  227. package/dist/clis/xiaohongshu/download.test.js +75 -0
  228. package/dist/clis/xiaohongshu/note-helpers.d.ts +12 -0
  229. package/dist/clis/xiaohongshu/note-helpers.js +23 -0
  230. package/dist/clis/xiaohongshu/note.d.ts +7 -0
  231. package/dist/clis/xiaohongshu/note.js +76 -0
  232. package/dist/clis/xiaohongshu/note.test.d.ts +1 -0
  233. package/dist/clis/xiaohongshu/note.test.js +136 -0
  234. package/dist/clis/xiaohongshu/publish.d.ts +1 -1
  235. package/dist/clis/xiaohongshu/publish.js +78 -31
  236. package/dist/clis/xiaohongshu/publish.test.js +66 -1
  237. package/dist/clis/xiaohongshu/search.js +9 -0
  238. package/dist/clis/xiaohongshu/search.test.js +10 -4
  239. package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
  240. package/dist/clis/xiaohongshu/user-helpers.js +2 -0
  241. package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
  242. package/dist/clis/xueqiu/comments.d.ts +118 -0
  243. package/dist/clis/xueqiu/comments.js +354 -0
  244. package/dist/clis/xueqiu/comments.test.d.ts +1 -0
  245. package/dist/clis/xueqiu/comments.test.js +696 -0
  246. package/dist/clis/youtube/search.js +57 -17
  247. package/dist/clis/youtube/transcript.js +2 -4
  248. package/dist/clis/youtube/utils.d.ts +9 -0
  249. package/dist/clis/youtube/utils.js +67 -3
  250. package/dist/clis/youtube/utils.test.d.ts +1 -0
  251. package/dist/clis/youtube/utils.test.js +37 -0
  252. package/dist/clis/youtube/video.js +16 -15
  253. package/dist/clis/zhihu/question.js +19 -17
  254. package/dist/clis/zhihu/question.test.d.ts +1 -0
  255. package/dist/clis/zhihu/question.test.js +54 -0
  256. package/dist/clis/zsxq/dynamics.d.ts +1 -0
  257. package/dist/clis/zsxq/dynamics.js +47 -0
  258. package/dist/clis/zsxq/groups.d.ts +1 -0
  259. package/dist/clis/zsxq/groups.js +32 -0
  260. package/dist/clis/zsxq/search.d.ts +1 -0
  261. package/dist/clis/zsxq/search.js +43 -0
  262. package/dist/clis/zsxq/search.test.d.ts +1 -0
  263. package/dist/clis/zsxq/search.test.js +24 -0
  264. package/dist/clis/zsxq/topic.d.ts +1 -0
  265. package/dist/clis/zsxq/topic.js +47 -0
  266. package/dist/clis/zsxq/topic.test.d.ts +1 -0
  267. package/dist/clis/zsxq/topic.test.js +29 -0
  268. package/dist/clis/zsxq/topics.d.ts +1 -0
  269. package/dist/clis/zsxq/topics.js +25 -0
  270. package/dist/clis/zsxq/topics.test.d.ts +1 -0
  271. package/dist/clis/zsxq/topics.test.js +24 -0
  272. package/dist/clis/zsxq/utils.d.ts +97 -0
  273. package/dist/clis/zsxq/utils.js +230 -0
  274. package/dist/commanderAdapter.js +10 -1
  275. package/dist/commanderAdapter.test.js +64 -0
  276. package/dist/commands/daemon.d.ts +9 -0
  277. package/dist/commands/daemon.js +124 -0
  278. package/dist/commands/daemon.test.d.ts +1 -0
  279. package/dist/commands/daemon.test.js +185 -0
  280. package/dist/completion.js +3 -1
  281. package/dist/constants.d.ts +2 -0
  282. package/dist/constants.js +2 -0
  283. package/dist/daemon.d.ts +1 -1
  284. package/dist/daemon.js +25 -14
  285. package/dist/daemon.test.d.ts +1 -0
  286. package/dist/daemon.test.js +65 -0
  287. package/dist/discovery.d.ts +9 -0
  288. package/dist/discovery.js +47 -2
  289. package/dist/electron-apps.d.ts +29 -0
  290. package/dist/electron-apps.js +65 -0
  291. package/dist/electron-apps.test.d.ts +1 -0
  292. package/dist/electron-apps.test.js +43 -0
  293. package/dist/engine.test.js +41 -9
  294. package/dist/execution.js +20 -16
  295. package/dist/external-clis.yaml +17 -0
  296. package/dist/idle-manager.d.ts +19 -0
  297. package/dist/idle-manager.js +54 -0
  298. package/dist/launcher.d.ts +36 -0
  299. package/dist/launcher.js +152 -0
  300. package/dist/launcher.test.d.ts +1 -0
  301. package/dist/launcher.test.js +57 -0
  302. package/dist/main.js +3 -3
  303. package/dist/registry.d.ts +1 -0
  304. package/dist/registry.js +31 -3
  305. package/dist/registry.test.js +13 -0
  306. package/dist/runtime.d.ts +5 -3
  307. package/dist/runtime.js +12 -5
  308. package/dist/serialization.d.ts +1 -0
  309. package/dist/serialization.js +3 -0
  310. package/dist/serialization.test.js +17 -1
  311. package/dist/tui.d.ts +7 -0
  312. package/dist/tui.js +52 -0
  313. package/dist/tui.test.d.ts +1 -0
  314. package/dist/tui.test.js +19 -0
  315. package/dist/types.d.ts +5 -0
  316. package/dist/weixin-download.test.js +14 -0
  317. package/docs/.vitepress/config.mts +4 -0
  318. package/docs/adapters/browser/band.md +63 -0
  319. package/docs/adapters/browser/notebooklm.md +69 -0
  320. package/docs/adapters/browser/ones.md +59 -0
  321. package/docs/adapters/browser/spotify.md +62 -0
  322. package/docs/adapters/browser/tieba.md +45 -0
  323. package/docs/adapters/browser/xiaohongshu.md +19 -10
  324. package/docs/adapters/browser/xueqiu.md +5 -0
  325. package/docs/adapters/browser/zsxq.md +49 -0
  326. package/docs/adapters/index.md +67 -63
  327. package/docs/adapters-doc/ones.md +32 -0
  328. package/docs/guide/browser-bridge.md +12 -0
  329. package/docs/guide/troubleshooting.md +9 -4
  330. package/docs/superpowers/plans/2026-03-31-daemon-lifecycle-redesign.md +857 -0
  331. package/docs/superpowers/specs/2026-03-31-daemon-lifecycle-redesign.md +208 -0
  332. package/docs/zh/guide/browser-bridge.md +12 -0
  333. package/extension/dist/background.js +794 -513
  334. package/extension/src/background.test.ts +202 -2
  335. package/extension/src/background.ts +189 -10
  336. package/extension/src/cdp.ts +54 -0
  337. package/extension/src/protocol.ts +11 -5
  338. package/package.json +1 -1
  339. package/scripts/postinstall.js +16 -0
  340. package/src/browser/cdp.ts +24 -17
  341. package/src/browser/daemon-client.ts +11 -1
  342. package/src/browser/dom-helpers.test.ts +15 -1
  343. package/src/browser/dom-helpers.ts +1 -0
  344. package/src/browser/mcp.ts +18 -13
  345. package/src/browser/page.test.ts +58 -0
  346. package/src/browser/page.ts +34 -2
  347. package/src/browser/stealth.test.ts +153 -0
  348. package/src/browser/stealth.ts +198 -0
  349. package/src/browser.test.ts +1 -1
  350. package/src/build-manifest.test.ts +2 -0
  351. package/src/build-manifest.ts +6 -1
  352. package/src/cli.ts +21 -3
  353. package/src/clis/antigravity/SKILL.md +3 -12
  354. package/src/clis/antigravity/serve.ts +5 -10
  355. package/src/clis/band/bands.ts +76 -0
  356. package/src/clis/band/mentions.ts +134 -0
  357. package/src/clis/band/post.ts +187 -0
  358. package/src/clis/band/posts.ts +106 -0
  359. package/src/clis/bilibili/subtitle.test.ts +60 -0
  360. package/src/clis/bilibili/subtitle.ts +4 -0
  361. package/src/clis/chatwise/ask.ts +0 -2
  362. package/src/clis/chatwise/export.ts +0 -2
  363. package/src/clis/chatwise/history.ts +0 -2
  364. package/src/clis/chatwise/model.ts +0 -2
  365. package/src/clis/chatwise/new.ts +1 -2
  366. package/src/clis/chatwise/read.ts +0 -2
  367. package/src/clis/chatwise/screenshot.ts +1 -2
  368. package/src/clis/chatwise/send.ts +0 -2
  369. package/src/clis/chatwise/status.ts +1 -2
  370. package/src/clis/ctrip/search.test.ts +73 -0
  371. package/src/clis/ctrip/search.ts +97 -47
  372. package/src/clis/doubao/detail.test.ts +53 -0
  373. package/src/clis/doubao/detail.ts +41 -0
  374. package/src/clis/doubao/history.test.ts +45 -0
  375. package/src/clis/doubao/history.ts +32 -0
  376. package/src/clis/doubao/meeting-summary.ts +53 -0
  377. package/src/clis/doubao/meeting-transcript.ts +48 -0
  378. package/src/clis/doubao/utils.test.ts +45 -0
  379. package/src/clis/doubao/utils.ts +371 -0
  380. package/src/clis/douyin/_shared/public-api.ts +84 -0
  381. package/src/clis/douyin/_shared/sts2.test.ts +31 -0
  382. package/src/clis/douyin/_shared/sts2.ts +11 -3
  383. package/src/clis/douyin/activities.test.ts +41 -1
  384. package/src/clis/douyin/activities.ts +12 -3
  385. package/src/clis/douyin/collections.test.ts +35 -2
  386. package/src/clis/douyin/collections.ts +1 -1
  387. package/src/clis/douyin/draft.test.ts +444 -2
  388. package/src/clis/douyin/draft.ts +382 -218
  389. package/src/clis/douyin/hashtag.test.ts +42 -2
  390. package/src/clis/douyin/hashtag.ts +11 -3
  391. package/src/clis/douyin/profile.test.ts +43 -1
  392. package/src/clis/douyin/profile.ts +9 -2
  393. package/src/clis/douyin/user-videos.test.ts +122 -0
  394. package/src/clis/douyin/user-videos.ts +101 -0
  395. package/src/clis/douyin/videos.test.ts +52 -2
  396. package/src/clis/douyin/videos.ts +49 -15
  397. package/src/clis/facebook/search.test.ts +70 -0
  398. package/src/clis/facebook/search.yaml +4 -3
  399. package/src/clis/instagram/download.test.ts +159 -0
  400. package/src/clis/instagram/download.ts +286 -0
  401. package/src/clis/notebooklm/bind-current.test.ts +43 -0
  402. package/src/clis/notebooklm/bind-current.ts +36 -0
  403. package/src/clis/notebooklm/binding.test.ts +53 -0
  404. package/src/clis/notebooklm/compat.test.ts +19 -0
  405. package/src/clis/notebooklm/current.ts +38 -0
  406. package/src/clis/notebooklm/get.ts +53 -0
  407. package/src/clis/notebooklm/history.test.ts +70 -0
  408. package/src/clis/notebooklm/history.ts +36 -0
  409. package/src/clis/notebooklm/list.ts +40 -0
  410. package/src/clis/notebooklm/note-list.test.ts +64 -0
  411. package/src/clis/notebooklm/note-list.ts +42 -0
  412. package/src/clis/notebooklm/notes-get.test.ts +88 -0
  413. package/src/clis/notebooklm/notes-get.ts +67 -0
  414. package/src/clis/notebooklm/rpc.test.ts +126 -0
  415. package/src/clis/notebooklm/rpc.ts +286 -0
  416. package/src/clis/notebooklm/shared.ts +98 -0
  417. package/src/clis/notebooklm/source-fulltext.test.ts +123 -0
  418. package/src/clis/notebooklm/source-fulltext.ts +69 -0
  419. package/src/clis/notebooklm/source-get.test.ts +100 -0
  420. package/src/clis/notebooklm/source-get.ts +60 -0
  421. package/src/clis/notebooklm/source-guide.test.ts +121 -0
  422. package/src/clis/notebooklm/source-guide.ts +69 -0
  423. package/src/clis/notebooklm/source-list.ts +45 -0
  424. package/src/clis/notebooklm/status.ts +34 -0
  425. package/src/clis/notebooklm/summary.test.ts +94 -0
  426. package/src/clis/notebooklm/summary.ts +45 -0
  427. package/src/clis/notebooklm/utils.test.ts +446 -0
  428. package/src/clis/notebooklm/utils.ts +893 -0
  429. package/src/clis/ones/common.ts +187 -0
  430. package/src/clis/ones/enrich-tasks.ts +47 -0
  431. package/src/clis/ones/login.ts +103 -0
  432. package/src/clis/ones/logout.ts +19 -0
  433. package/src/clis/ones/me.ts +34 -0
  434. package/src/clis/ones/my-tasks.ts +148 -0
  435. package/src/clis/ones/resolve-labels.ts +80 -0
  436. package/src/clis/ones/task-helpers.test.ts +14 -0
  437. package/src/clis/ones/task-helpers.ts +214 -0
  438. package/src/clis/ones/task.ts +79 -0
  439. package/src/clis/ones/tasks.ts +92 -0
  440. package/src/clis/ones/token-info.ts +46 -0
  441. package/src/clis/ones/worklog.test.ts +24 -0
  442. package/src/clis/ones/worklog.ts +306 -0
  443. package/src/clis/spotify/spotify.ts +328 -0
  444. package/src/clis/spotify/utils.test.ts +87 -0
  445. package/src/clis/spotify/utils.ts +92 -0
  446. package/src/clis/substack/utils.test.ts +54 -0
  447. package/src/clis/substack/utils.ts +10 -2
  448. package/src/clis/tieba/commands.test.ts +86 -0
  449. package/src/clis/tieba/hot.ts +52 -0
  450. package/src/clis/tieba/posts.ts +108 -0
  451. package/src/clis/tieba/read.ts +158 -0
  452. package/src/clis/tieba/search.ts +119 -0
  453. package/src/clis/tieba/utils.test.ts +322 -0
  454. package/src/clis/tieba/utils.ts +348 -0
  455. package/src/clis/v2ex/hot.yaml +4 -1
  456. package/src/clis/v2ex/latest.yaml +4 -1
  457. package/src/clis/v2ex/topic.yaml +6 -1
  458. package/src/clis/weixin/download.ts +95 -6
  459. package/src/clis/weread/book.ts +256 -13
  460. package/src/clis/weread/commands.test.ts +409 -0
  461. package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
  462. package/src/clis/weread/search-regression.test.ts +440 -0
  463. package/src/clis/weread/search.ts +189 -9
  464. package/src/clis/weread/shelf.ts +20 -122
  465. package/src/clis/weread/utils.test.ts +81 -1
  466. package/src/clis/weread/utils.ts +293 -7
  467. package/src/clis/xiaohongshu/comments.test.ts +85 -9
  468. package/src/clis/xiaohongshu/comments.ts +76 -17
  469. package/src/clis/xiaohongshu/download.test.ts +96 -0
  470. package/src/clis/xiaohongshu/download.ts +83 -22
  471. package/src/clis/xiaohongshu/note-helpers.ts +25 -0
  472. package/src/clis/xiaohongshu/note.test.ts +164 -0
  473. package/src/clis/xiaohongshu/note.ts +86 -0
  474. package/src/clis/xiaohongshu/publish.test.ts +79 -1
  475. package/src/clis/xiaohongshu/publish.ts +84 -30
  476. package/src/clis/xiaohongshu/search.test.ts +11 -4
  477. package/src/clis/xiaohongshu/search.ts +13 -0
  478. package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
  479. package/src/clis/xiaohongshu/user-helpers.ts +4 -0
  480. package/src/clis/xueqiu/comments.test.ts +823 -0
  481. package/src/clis/xueqiu/comments.ts +461 -0
  482. package/src/clis/youtube/search.ts +57 -17
  483. package/src/clis/youtube/transcript.ts +2 -4
  484. package/src/clis/youtube/utils.test.ts +43 -0
  485. package/src/clis/youtube/utils.ts +69 -0
  486. package/src/clis/youtube/video.ts +16 -15
  487. package/src/clis/zhihu/question.test.ts +71 -0
  488. package/src/clis/zhihu/question.ts +27 -15
  489. package/src/clis/zsxq/dynamics.ts +60 -0
  490. package/src/clis/zsxq/groups.ts +41 -0
  491. package/src/clis/zsxq/search.test.ts +29 -0
  492. package/src/clis/zsxq/search.ts +54 -0
  493. package/src/clis/zsxq/topic.test.ts +34 -0
  494. package/src/clis/zsxq/topic.ts +68 -0
  495. package/src/clis/zsxq/topics.test.ts +29 -0
  496. package/src/clis/zsxq/topics.ts +36 -0
  497. package/src/clis/zsxq/utils.ts +351 -0
  498. package/src/commanderAdapter.test.ts +77 -0
  499. package/src/commanderAdapter.ts +8 -1
  500. package/src/commands/daemon.test.ts +238 -0
  501. package/src/commands/daemon.ts +135 -0
  502. package/src/completion.ts +2 -1
  503. package/src/constants.ts +3 -0
  504. package/src/daemon.test.ts +88 -0
  505. package/src/daemon.ts +26 -14
  506. package/src/discovery.ts +52 -2
  507. package/src/electron-apps.test.ts +50 -0
  508. package/src/electron-apps.ts +89 -0
  509. package/src/engine.test.ts +45 -9
  510. package/src/execution.ts +24 -19
  511. package/src/external-clis.yaml +17 -0
  512. package/src/idle-manager.ts +60 -0
  513. package/src/launcher.test.ts +67 -0
  514. package/src/launcher.ts +185 -0
  515. package/src/main.ts +3 -2
  516. package/src/registry.test.ts +15 -0
  517. package/src/registry.ts +32 -3
  518. package/src/runtime.ts +13 -7
  519. package/src/serialization.test.ts +19 -1
  520. package/src/serialization.ts +2 -0
  521. package/src/tui.test.ts +23 -0
  522. package/src/tui.ts +65 -0
  523. package/src/types.ts +5 -0
  524. package/src/weixin-download.test.ts +27 -0
  525. package/tests/e2e/band-auth.test.ts +20 -0
  526. package/tests/e2e/browser-auth-helpers.ts +18 -0
  527. package/tests/e2e/browser-auth.test.ts +35 -47
  528. package/tests/e2e/browser-public-extended.test.ts +6 -2
  529. package/tests/e2e/browser-public.test.ts +288 -0
  530. package/tests/e2e/management.test.ts +1 -1
  531. package/tests/e2e/plugin-management.test.ts +1 -1
  532. package/vitest.config.ts +1 -0
  533. package/chatwise-opencli.ps1 +0 -82
  534. package/dist/clis/chatwise/shared.d.ts +0 -2
  535. package/dist/clis/chatwise/shared.js +0 -6
  536. package/dist/weread-private-api-regression.test.d.ts +0 -1
  537. package/dist/weread-search-regression.test.d.ts +0 -1
  538. package/dist/weread-search-regression.test.js +0 -39
  539. package/src/clis/chatwise/shared.ts +0 -8
  540. package/src/weread-search-regression.test.ts +0 -44
@@ -0,0 +1,80 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { CliError } from '../../errors.js';
3
+ import { getOnesBaseUrl, onesFetchInPage } from './common.js';
4
+ cli({
5
+ site: 'ones',
6
+ name: 'login',
7
+ description: 'ONES Project API — login via Chrome Bridge (POST auth/login); stderr prints export hints for ONES_USER_ID / TOKEN',
8
+ domain: 'ones.cn',
9
+ strategy: Strategy.COOKIE,
10
+ browser: true,
11
+ navigateBefore: false,
12
+ args: [
13
+ {
14
+ name: 'email',
15
+ type: 'str',
16
+ required: false,
17
+ help: 'Account email (or set ONES_EMAIL)',
18
+ },
19
+ {
20
+ name: 'phone',
21
+ type: 'str',
22
+ required: false,
23
+ help: 'Account phone (or set ONES_PHONE); ignored if email is set',
24
+ },
25
+ {
26
+ name: 'password',
27
+ type: 'str',
28
+ required: false,
29
+ help: 'Password (or set ONES_PASSWORD)',
30
+ },
31
+ ],
32
+ columns: ['uuid', 'name', 'email', 'token_preview'],
33
+ func: async (page, kwargs) => {
34
+ const email = kwargs.email?.trim() || process.env.ONES_EMAIL?.trim();
35
+ const phone = kwargs.phone?.trim() || process.env.ONES_PHONE?.trim();
36
+ const password = kwargs.password || process.env.ONES_PASSWORD || '';
37
+ if (!password) {
38
+ throw new CliError('CONFIG', 'Password required', 'Pass --password or set ONES_PASSWORD for non-interactive use.');
39
+ }
40
+ if (!email && !phone) {
41
+ throw new CliError('CONFIG', 'email or phone required', 'Pass --email or --phone (or set ONES_EMAIL / ONES_PHONE).');
42
+ }
43
+ getOnesBaseUrl();
44
+ const bodyObj = { password };
45
+ if (email)
46
+ bodyObj.email = email;
47
+ else
48
+ bodyObj.phone = phone;
49
+ const parsed = (await onesFetchInPage(page, 'auth/login', {
50
+ method: 'POST',
51
+ body: JSON.stringify(bodyObj),
52
+ auth: false,
53
+ }));
54
+ const user = parsed.user;
55
+ if (!user?.uuid || !user?.token) {
56
+ throw new CliError('FETCH_ERROR', 'ONES login response missing user.uuid or user.token', 'Your server build may differ from documented Project API.');
57
+ }
58
+ const uuid = String(user.uuid);
59
+ const token = String(user.token);
60
+ const name = String(user.name ?? '');
61
+ const em = String(user.email ?? '');
62
+ const base = getOnesBaseUrl();
63
+ console.error([
64
+ '',
65
+ '后续请求会优先使用当前 Chrome 会话 Cookie;若接口仍要求 Header,可 export:',
66
+ ` export ONES_BASE_URL=${JSON.stringify(base)}`,
67
+ ` export ONES_USER_ID=${JSON.stringify(uuid)}`,
68
+ ` export ONES_AUTH_TOKEN=${JSON.stringify(token)}`,
69
+ '',
70
+ ].join('\n'));
71
+ return [
72
+ {
73
+ uuid,
74
+ name,
75
+ email: em,
76
+ token_preview: token.length > 12 ? `${token.slice(0, 6)}…${token.slice(-4)}` : '***',
77
+ },
78
+ ];
79
+ },
80
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { onesFetchInPage } from './common.js';
3
+ cli({
4
+ site: 'ones',
5
+ name: 'logout',
6
+ description: 'ONES Project API — invalidate current token (GET auth/logout) via Chrome Bridge',
7
+ domain: 'ones.cn',
8
+ strategy: Strategy.COOKIE,
9
+ browser: true,
10
+ navigateBefore: false,
11
+ args: [],
12
+ columns: ['ok', 'detail'],
13
+ func: async (page) => {
14
+ await onesFetchInPage(page, 'auth/logout', { method: 'GET' });
15
+ return [{ ok: 'true', detail: 'Server logout ok; clear local ONES_AUTH_TOKEN if set.' }];
16
+ },
17
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { CliError } from '../../errors.js';
3
+ import { onesFetchInPage } from './common.js';
4
+ cli({
5
+ site: 'ones',
6
+ name: 'me',
7
+ description: 'ONES Project API — current user (GET users/me) via Chrome Bridge',
8
+ domain: 'ones.cn',
9
+ strategy: Strategy.COOKIE,
10
+ browser: true,
11
+ navigateBefore: false,
12
+ args: [],
13
+ columns: ['uuid', 'name', 'email', 'phone', 'status'],
14
+ func: async (page) => {
15
+ const data = (await onesFetchInPage(page, 'users/me'));
16
+ const u = data.user && typeof data.user === 'object' ? data.user : data;
17
+ if (!u || typeof u.uuid !== 'string') {
18
+ throw new CliError('FETCH_ERROR', 'Unexpected users/me response', 'See raw JSON with: opencli ones me -f json');
19
+ }
20
+ return [
21
+ {
22
+ uuid: String(u.uuid),
23
+ name: String(u.name ?? ''),
24
+ email: String(u.email ?? ''),
25
+ phone: String(u.phone ?? ''),
26
+ status: u.status != null ? String(u.status) : '',
27
+ },
28
+ ];
29
+ },
30
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,120 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { CliError } from '../../errors.js';
3
+ import { gotoOnesHome, onesFetchInPage, resolveOnesUserUuid } from './common.js';
4
+ import { enrichPeekEntriesWithDetails } from './enrich-tasks.js';
5
+ import { resolveTaskListLabels } from './resolve-labels.js';
6
+ import { defaultPeekBody, flattenPeekGroups, mapTaskEntry, parsePeekLimit, } from './task-helpers.js';
7
+ /** 文档示例里「负责人」常用 field004;与顶层 assign 在不同部署上二选一有效 */
8
+ function queryAssign(userUuid) {
9
+ return { must: [{ equal: { assign: userUuid } }] };
10
+ }
11
+ function queryAssignField004(userUuid) {
12
+ return { must: [{ in: { 'field_values.field004': [userUuid] } }] };
13
+ }
14
+ function queryOwner(userUuid) {
15
+ return { must: [{ equal: { owner: userUuid } }] };
16
+ }
17
+ function dedupeByUuid(entries) {
18
+ const seen = new Set();
19
+ const out = [];
20
+ for (const e of entries) {
21
+ const id = String(e.uuid ?? '');
22
+ if (!id || seen.has(id))
23
+ continue;
24
+ seen.add(id);
25
+ out.push(e);
26
+ }
27
+ return out;
28
+ }
29
+ async function peekTasks(page, team, query, cap) {
30
+ const path = `team/${team}/filters/peek`;
31
+ const body = defaultPeekBody(query);
32
+ const parsed = (await onesFetchInPage(page, path, {
33
+ method: 'POST',
34
+ body: JSON.stringify(body),
35
+ skipGoto: true,
36
+ }));
37
+ return flattenPeekGroups(parsed, cap);
38
+ }
39
+ cli({
40
+ site: 'ones',
41
+ name: 'my-tasks',
42
+ description: 'ONES — my work items (filters/peek + strict must query). Default: assignee=me. Use --mode if your site uses field004 for assignee.',
43
+ domain: 'ones.cn',
44
+ strategy: Strategy.COOKIE,
45
+ browser: true,
46
+ navigateBefore: false,
47
+ args: [
48
+ {
49
+ name: 'team',
50
+ type: 'str',
51
+ required: false,
52
+ positional: true,
53
+ help: 'Team UUID from URL …/team/<uuid>/…, or set ONES_TEAM_UUID',
54
+ },
55
+ {
56
+ name: 'limit',
57
+ type: 'int',
58
+ default: 100,
59
+ help: 'Max rows (default 100, max 500)',
60
+ },
61
+ {
62
+ name: 'mode',
63
+ type: 'str',
64
+ default: 'assign',
65
+ choices: ['assign', 'field004', 'owner', 'both'],
66
+ help: 'assign=负责人(顶层 assign);field004=负责人(筛选器示例里的 field004);owner=创建者;both=负责人∪创建者(两次 peek 去重)',
67
+ },
68
+ ],
69
+ columns: ['title', 'status', 'project', 'uuid', 'updated', '工时'],
70
+ func: async (page, kwargs) => {
71
+ const team = kwargs.team?.trim() ||
72
+ process.env.ONES_TEAM_UUID?.trim() ||
73
+ process.env.ONES_TEAM_ID?.trim();
74
+ if (!team) {
75
+ throw new CliError('CONFIG', 'team UUID required', 'Pass team from URL …/team/<team>/… or set ONES_TEAM_UUID.');
76
+ }
77
+ const limit = parsePeekLimit(kwargs.limit, 100);
78
+ const mode = String(kwargs.mode ?? 'assign');
79
+ await gotoOnesHome(page);
80
+ const userUuid = await resolveOnesUserUuid(page, { skipGoto: true });
81
+ let entries = [];
82
+ if (mode === 'both') {
83
+ const cap = Math.min(500, limit * 2);
84
+ const asAssign = await peekTasks(page, team, queryAssign(userUuid), cap);
85
+ const asOwner = await peekTasks(page, team, queryOwner(userUuid), cap);
86
+ entries = dedupeByUuid([...asAssign, ...asOwner]).slice(0, limit);
87
+ }
88
+ else {
89
+ const queryByMode = () => {
90
+ switch (mode) {
91
+ case 'field004':
92
+ return queryAssignField004(userUuid);
93
+ case 'owner':
94
+ return queryOwner(userUuid);
95
+ case 'assign':
96
+ default:
97
+ return queryAssign(userUuid);
98
+ }
99
+ };
100
+ const primary = queryByMode();
101
+ try {
102
+ entries = await peekTasks(page, team, primary, limit);
103
+ }
104
+ catch (e) {
105
+ const msg = e instanceof Error ? e.message : '';
106
+ const canFallback = mode === 'assign' &&
107
+ (msg.includes('ServerError') || msg.includes('801') || msg.includes('Params is invalid'));
108
+ if (canFallback) {
109
+ entries = await peekTasks(page, team, queryAssignField004(userUuid), limit);
110
+ }
111
+ else {
112
+ throw e;
113
+ }
114
+ }
115
+ }
116
+ const enriched = await enrichPeekEntriesWithDetails(page, team, entries, true);
117
+ const labels = await resolveTaskListLabels(page, team, enriched, true);
118
+ return enriched.map((e) => mapTaskEntry(e, labels));
119
+ },
120
+ });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 把 status / project 的 uuid 解析为中文名(团队级接口各查一次或按批)
3
+ */
4
+ import type { IPage } from '../../types.js';
5
+ export declare function loadTaskStatusLabels(page: IPage, team: string, skipGoto: boolean): Promise<Map<string, string>>;
6
+ export declare function loadProjectLabels(page: IPage, team: string, projectUuids: string[], skipGoto: boolean): Promise<Map<string, string>>;
7
+ export declare function resolveTaskListLabels(page: IPage, team: string, entries: Record<string, unknown>[], skipGoto: boolean): Promise<{
8
+ statusByUuid: Map<string, string>;
9
+ projectByUuid: Map<string, string>;
10
+ }>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * 把 status / project 的 uuid 解析为中文名(团队级接口各查一次或按批)
3
+ */
4
+ import { onesFetchInPage } from './common.js';
5
+ import { getTaskProjectRawId } from './task-helpers.js';
6
+ export async function loadTaskStatusLabels(page, team, skipGoto) {
7
+ const map = new Map();
8
+ try {
9
+ const parsed = (await onesFetchInPage(page, `team/${team}/task_statuses`, {
10
+ method: 'GET',
11
+ skipGoto,
12
+ }));
13
+ const list = Array.isArray(parsed.task_statuses)
14
+ ? parsed.task_statuses
15
+ : [];
16
+ for (const s of list) {
17
+ const id = String(s.uuid ?? '');
18
+ const name = String(s.name ?? '');
19
+ if (id && name)
20
+ map.set(id, name);
21
+ }
22
+ }
23
+ catch {
24
+ /* 降级为仅显示 uuid */
25
+ }
26
+ return map;
27
+ }
28
+ const PROJECT_INFO_CHUNK = 25;
29
+ export async function loadProjectLabels(page, team, projectUuids, skipGoto) {
30
+ const map = new Map();
31
+ const ids = [...new Set(projectUuids.filter(Boolean))];
32
+ if (ids.length === 0)
33
+ return map;
34
+ try {
35
+ for (let i = 0; i < ids.length; i += PROJECT_INFO_CHUNK) {
36
+ const slice = ids.slice(i, i + PROJECT_INFO_CHUNK);
37
+ const q = slice.map(encodeURIComponent).join(',');
38
+ const path = `team/${team}/projects/info?ids=${q}`;
39
+ const parsed = (await onesFetchInPage(page, path, {
40
+ method: 'GET',
41
+ skipGoto,
42
+ }));
43
+ const projects = Array.isArray(parsed.projects) ? parsed.projects : [];
44
+ for (const p of projects) {
45
+ const id = String(p.uuid ?? '');
46
+ const name = String(p.name ?? '');
47
+ if (id && name)
48
+ map.set(id, name);
49
+ }
50
+ }
51
+ }
52
+ catch {
53
+ /* 降级 */
54
+ }
55
+ return map;
56
+ }
57
+ export async function resolveTaskListLabels(page, team, entries, skipGoto) {
58
+ const projectUuids = entries.map((e) => getTaskProjectRawId(e)).filter(Boolean);
59
+ const [statusByUuid, projectByUuid] = await Promise.all([
60
+ loadTaskStatusLabels(page, team, skipGoto),
61
+ loadProjectLabels(page, team, projectUuids, skipGoto),
62
+ ]);
63
+ return { statusByUuid, projectByUuid };
64
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * ONES filters/peek 响应解析(tasks / my-tasks 共用)
3
+ */
4
+ export declare function pickTaskTitle(e: Record<string, unknown>): string;
5
+ /** 表格里标题别撑爆终端 */
6
+ export declare function ellipsizeCell(s: string, max?: number): string;
7
+ /** 辅助列:长 uuid 缩略,完整值见 -f json */
8
+ export declare function briefUuid(id: string, head?: number, tail?: number): string;
9
+ export declare function formatStamp(v: unknown): string;
10
+ export declare function flattenPeekGroups(parsed: Record<string, unknown>, limit: number): Record<string, unknown>[];
11
+ /** 工作项状态 uuid(用于查 task_statuses 得中文名) */
12
+ export declare function getTaskStatusRawId(e: Record<string, unknown>): string;
13
+ /** 项目 uuid */
14
+ export declare function getTaskProjectRawId(e: Record<string, unknown>): string;
15
+ /**
16
+ * Project API 里 assess/total/remaining_manhour 多为**定点整数**(与 Web 上「小时」不一致);
17
+ * 常见换算:raw / 1e5 ≈ 小时。若你方实例不同,可设 `ONES_MANHOUR_SCALE`(默认 100000)。
18
+ */
19
+ export declare function onesManhourScale(): number;
20
+ /** 界面/h 小数 → API 内 manhour 整数(与列表「工时」列同一刻度) */
21
+ export declare function hoursToOnesManhourRaw(hours: number): number;
22
+ export declare function formatTaskManhourSummary(e: Record<string, unknown>): string;
23
+ export interface TaskLabelMaps {
24
+ statusByUuid?: Map<string, string>;
25
+ projectByUuid?: Map<string, string>;
26
+ }
27
+ export declare function mapTaskEntry(e: Record<string, unknown>, labels?: TaskLabelMaps): Record<string, string>;
28
+ export declare function defaultPeekBody(query: Record<string, unknown>): Record<string, unknown>;
29
+ export declare function parsePeekLimit(value: unknown, fallback: number): number;
@@ -0,0 +1,212 @@
1
+ /**
2
+ * ONES filters/peek 响应解析(tasks / my-tasks 共用)
3
+ */
4
+ import { CliError } from '../../errors.js';
5
+ /** ONES task 里 field_values 常为 [{ field_uuid, value }, ...] */
6
+ function pickTitleFromFieldValuesArray(fv) {
7
+ if (!Array.isArray(fv))
8
+ return '';
9
+ for (const item of fv) {
10
+ if (!item || typeof item !== 'object')
11
+ continue;
12
+ const row = item;
13
+ const fu = String(row.field_uuid ?? '');
14
+ if (!fu.startsWith('field'))
15
+ continue;
16
+ const v = row.value;
17
+ if (typeof v === 'string' && v.trim())
18
+ return v.trim();
19
+ if (Array.isArray(v) && v.length && typeof v[0] === 'string' && v[0].trim())
20
+ return v[0].trim();
21
+ }
22
+ return '';
23
+ }
24
+ export function pickTaskTitle(e) {
25
+ for (const k of ['summary', 'name', 'title', 'subject']) {
26
+ const v = e[k];
27
+ if (typeof v === 'string' && v.trim())
28
+ return v.trim();
29
+ }
30
+ const fromArr = pickTitleFromFieldValuesArray(e.field_values);
31
+ if (fromArr)
32
+ return fromArr;
33
+ const fv = e.field_values;
34
+ if (fv && typeof fv === 'object' && !Array.isArray(fv)) {
35
+ const o = fv;
36
+ for (const k of ['field001', 'field002', 'field003']) {
37
+ const v = o[k];
38
+ if (typeof v === 'string' && v.trim())
39
+ return v.trim();
40
+ }
41
+ }
42
+ return '';
43
+ }
44
+ /** 表格里标题别撑爆终端 */
45
+ export function ellipsizeCell(s, max = 64) {
46
+ const t = s.trim();
47
+ if (t.length <= max)
48
+ return t;
49
+ return `${t.slice(0, max - 1)}…`;
50
+ }
51
+ /** 辅助列:长 uuid 缩略,完整值见 -f json */
52
+ export function briefUuid(id, head = 6, tail = 4) {
53
+ if (!id)
54
+ return '';
55
+ if (id.length <= head + tail + 1)
56
+ return id;
57
+ return `${id.slice(0, head)}…${id.slice(-tail)}`;
58
+ }
59
+ export function formatStamp(v) {
60
+ if (v == null || v === '')
61
+ return '';
62
+ const n = Number(v);
63
+ if (Number.isNaN(n))
64
+ return String(v);
65
+ const ms = n > 1e14 ? Math.floor(n / 1000) : n > 1e12 ? n : n * 1000;
66
+ try {
67
+ return new Date(ms).toISOString().replace('T', ' ').slice(0, 19);
68
+ }
69
+ catch {
70
+ return String(v);
71
+ }
72
+ }
73
+ export function flattenPeekGroups(parsed, limit) {
74
+ if (!Array.isArray(parsed.groups)) {
75
+ throw new CliError('FETCH_ERROR', 'Unexpected filters/peek response (missing groups)', 'Try -f json; check team UUID and API version.');
76
+ }
77
+ const groups = parsed.groups;
78
+ const rows = [];
79
+ for (const g of groups) {
80
+ const entries = Array.isArray(g.entries) ? g.entries : [];
81
+ for (const e of entries) {
82
+ rows.push(e);
83
+ if (rows.length >= limit)
84
+ break;
85
+ }
86
+ if (rows.length >= limit)
87
+ break;
88
+ }
89
+ return rows.slice(0, limit);
90
+ }
91
+ function fieldArrayFirstString(fv, fieldUuid) {
92
+ if (!Array.isArray(fv))
93
+ return '';
94
+ for (const item of fv) {
95
+ if (!item || typeof item !== 'object')
96
+ continue;
97
+ const row = item;
98
+ if (String(row.field_uuid ?? '') !== fieldUuid)
99
+ continue;
100
+ const v = row.value;
101
+ if (typeof v === 'string')
102
+ return v;
103
+ if (Array.isArray(v) && v[0] != null)
104
+ return String(v[0]);
105
+ }
106
+ return '';
107
+ }
108
+ function fvRecord(e) {
109
+ const fv = e.field_values;
110
+ return fv && typeof fv === 'object' && !Array.isArray(fv) ? fv : null;
111
+ }
112
+ /** 工作项状态 uuid(用于查 task_statuses 得中文名) */
113
+ export function getTaskStatusRawId(e) {
114
+ const fv = e.field_values;
115
+ const fvObj = fvRecord(e);
116
+ if (typeof e.status_uuid === 'string')
117
+ return e.status_uuid;
118
+ return fieldArrayFirstString(fv, 'field016') || (fvObj ? String(fvObj.field016 ?? '') : '');
119
+ }
120
+ /** 项目 uuid */
121
+ export function getTaskProjectRawId(e) {
122
+ const fv = e.field_values;
123
+ const fvObj = fvRecord(e);
124
+ if (typeof e.project_uuid === 'string')
125
+ return e.project_uuid;
126
+ return fieldArrayFirstString(fv, 'field006') || (fvObj ? String(fvObj.field006 ?? '') : '');
127
+ }
128
+ /**
129
+ * Project API 里 assess/total/remaining_manhour 多为**定点整数**(与 Web 上「小时」不一致);
130
+ * 常见换算:raw / 1e5 ≈ 小时。若你方实例不同,可设 `ONES_MANHOUR_SCALE`(默认 100000)。
131
+ */
132
+ export function onesManhourScale() {
133
+ const raw = Number(process.env.ONES_MANHOUR_SCALE?.trim());
134
+ if (Number.isFinite(raw) && raw > 0)
135
+ return raw;
136
+ return 1e5;
137
+ }
138
+ /** 界面/h 小数 → API 内 manhour 整数(与列表「工时」列同一刻度) */
139
+ export function hoursToOnesManhourRaw(hours) {
140
+ if (!Number.isFinite(hours) || hours <= 0)
141
+ return 0;
142
+ return Math.max(1, Math.round(hours * onesManhourScale()));
143
+ }
144
+ function formatHoursShort(hours) {
145
+ if (!Number.isFinite(hours))
146
+ return '';
147
+ const snapped = Math.round(hours * 1e6) / 1e6;
148
+ const near = Math.round(snapped);
149
+ if (Math.abs(snapped - near) < 1e-5)
150
+ return `${near}h`;
151
+ const t = Math.round(snapped * 10) / 10;
152
+ return Number.isInteger(t) ? `${t}h` : `${t.toFixed(1)}h`;
153
+ }
154
+ function formatManhourSegment(label, v) {
155
+ if (v == null || v === '')
156
+ return null;
157
+ const n = Number(v);
158
+ if (!Number.isFinite(n))
159
+ return null;
160
+ const hours = n / onesManhourScale();
161
+ return `${label}${formatHoursShort(hours)}`;
162
+ }
163
+ export function formatTaskManhourSummary(e) {
164
+ const parts = [];
165
+ const a = formatManhourSegment('估', e.assess_manhour);
166
+ const t = formatManhourSegment('登', e.total_manhour);
167
+ const r = formatManhourSegment('余', e.remaining_manhour);
168
+ if (a)
169
+ parts.push(a);
170
+ if (t)
171
+ parts.push(t);
172
+ if (r)
173
+ parts.push(r);
174
+ return parts.length ? parts.join(' ') : '—';
175
+ }
176
+ export function mapTaskEntry(e, labels) {
177
+ const statusId = getTaskStatusRawId(e);
178
+ const projectId = getTaskProjectRawId(e);
179
+ const fullUuid = String(e.uuid ?? '');
180
+ const title = ellipsizeCell(pickTaskTitle(e));
181
+ const briefIfLong = (s) => (s.length > 14 ? briefUuid(s) : s);
182
+ const statusLabel = labels?.statusByUuid?.get(statusId) ?? briefIfLong(statusId);
183
+ const projectLabel = labels?.projectByUuid?.get(projectId) ?? briefIfLong(projectId);
184
+ return {
185
+ title,
186
+ status: ellipsizeCell(statusLabel, 20),
187
+ project: ellipsizeCell(projectLabel, 40),
188
+ uuid: fullUuid,
189
+ updated: formatStamp(e.server_update_stamp),
190
+ 工时: ellipsizeCell(formatTaskManhourSummary(e), 36),
191
+ };
192
+ }
193
+ export function defaultPeekBody(query) {
194
+ return {
195
+ with_boards: false,
196
+ boards: null,
197
+ query,
198
+ group_by: '',
199
+ sort: [{ create_time: { order: 'desc' } }],
200
+ include_subtasks: false,
201
+ include_status_uuid: true,
202
+ include_issue_type: false,
203
+ include_project_uuid: true,
204
+ is_show_derive: false,
205
+ };
206
+ }
207
+ export function parsePeekLimit(value, fallback) {
208
+ const parsed = Number.parseInt(String(value ?? ''), 10);
209
+ if (!Number.isFinite(parsed) || parsed <= 0)
210
+ return fallback;
211
+ return Math.max(1, Math.min(500, parsed));
212
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { parsePeekLimit } from './task-helpers.js';
3
+ describe('parsePeekLimit', () => {
4
+ it('returns the fallback when the input is not numeric', () => {
5
+ expect(parsePeekLimit('abc', 30)).toBe(30);
6
+ });
7
+ it('clamps the input into the supported range', () => {
8
+ expect(parsePeekLimit('0', 30)).toBe(30);
9
+ expect(parsePeekLimit('999', 30)).toBe(500);
10
+ expect(parsePeekLimit('42', 30)).toBe(42);
11
+ });
12
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ import { cli, Strategy } from '../../registry.js';
2
+ import { CliError } from '../../errors.js';
3
+ import { onesFetchInPage } from './common.js';
4
+ import { formatStamp } from './task-helpers.js';
5
+ /**
6
+ * 工作项详情 — 对应前端路由 …/team/<team>/filter/view/…/task/<uuid>
7
+ * API: GET team/:teamUUID/task/:taskUUIDOrNumber/info
8
+ * @see https://docs.ones.cn/project/open-api-doc/project/task.html
9
+ */
10
+ cli({
11
+ site: 'ones',
12
+ name: 'task',
13
+ description: 'ONES — work item detail (GET team/:team/task/:id/info); id is URL segment after …/task/',
14
+ domain: 'ones.cn',
15
+ strategy: Strategy.COOKIE,
16
+ browser: true,
17
+ navigateBefore: false,
18
+ args: [
19
+ {
20
+ name: 'id',
21
+ type: 'str',
22
+ required: true,
23
+ positional: true,
24
+ help: 'Work item UUID (often 16 chars) from …/task/<id>',
25
+ },
26
+ {
27
+ name: 'team',
28
+ type: 'str',
29
+ required: false,
30
+ help: 'Team UUID (8 chars from …/team/<team>/…), or set ONES_TEAM_UUID',
31
+ },
32
+ ],
33
+ columns: ['uuid', 'summary', 'number', 'status_uuid', 'assign', 'owner', 'project_uuid', 'updated'],
34
+ func: async (page, kwargs) => {
35
+ const id = String(kwargs.id ?? '').trim();
36
+ if (!id) {
37
+ throw new CliError('CONFIG', 'task id required', 'Pass the work item uuid from the URL path …/task/<id>');
38
+ }
39
+ const team = kwargs.team?.trim() ||
40
+ process.env.ONES_TEAM_UUID?.trim() ||
41
+ process.env.ONES_TEAM_ID?.trim();
42
+ if (!team) {
43
+ throw new CliError('CONFIG', 'team UUID required', 'Use --team <teamUUID> or set ONES_TEAM_UUID (from …/team/<team>/…).');
44
+ }
45
+ const path = `team/${team}/task/${encodeURIComponent(id)}/info`;
46
+ const data = (await onesFetchInPage(page, path, { method: 'GET' }));
47
+ if (typeof data.uuid !== 'string') {
48
+ const hint = typeof data.reason === 'string'
49
+ ? data.reason
50
+ : 'Use -f json to inspect response; check id length (often 16) and team.';
51
+ throw new CliError('FETCH_ERROR', `ONES task info: ${hint}`, 'Confirm task uuid and team match the browser URL.');
52
+ }
53
+ return [
54
+ {
55
+ uuid: String(data.uuid),
56
+ summary: String(data.summary ?? ''),
57
+ number: data.number != null ? String(data.number) : '',
58
+ status_uuid: String(data.status_uuid ?? ''),
59
+ assign: String(data.assign ?? ''),
60
+ owner: String(data.owner ?? ''),
61
+ project_uuid: String(data.project_uuid ?? ''),
62
+ updated: formatStamp(data.server_update_stamp),
63
+ },
64
+ ];
65
+ },
66
+ });
@@ -0,0 +1 @@
1
+ export {};