@jackwener/opencli 1.6.0 → 1.6.2

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 (390) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +27 -45
  4. package/README.zh-CN.md +32 -34
  5. package/autoresearch/browse-tasks.json +18 -20
  6. package/autoresearch/commands/debug.ts +163 -0
  7. package/autoresearch/commands/fix.ts +145 -0
  8. package/autoresearch/commands/plan.ts +88 -0
  9. package/autoresearch/commands/run.ts +138 -0
  10. package/autoresearch/config.ts +82 -0
  11. package/autoresearch/engine.ts +359 -0
  12. package/autoresearch/eval-all.ts +127 -0
  13. package/autoresearch/eval-browse.ts +1 -1
  14. package/autoresearch/eval-publish.ts +238 -0
  15. package/autoresearch/eval-save.ts +249 -0
  16. package/autoresearch/eval-skill.ts +14 -8
  17. package/autoresearch/eval-v2ex.ts +220 -0
  18. package/autoresearch/eval-zhihu.ts +230 -0
  19. package/autoresearch/logger.ts +69 -0
  20. package/autoresearch/presets/combined-reliability.ts +27 -0
  21. package/autoresearch/presets/index.ts +23 -0
  22. package/autoresearch/presets/operate-reliability.ts +24 -0
  23. package/autoresearch/presets/save-reliability.ts +26 -0
  24. package/autoresearch/presets/skill-quality.ts +20 -0
  25. package/autoresearch/presets/v2ex-reliability.ts +24 -0
  26. package/autoresearch/presets/zhihu-reliability.ts +25 -0
  27. package/autoresearch/publish-tasks.json +345 -0
  28. package/autoresearch/run-save.sh +11 -0
  29. package/autoresearch/save-adapters/xhs-explore-deep.ts +64 -0
  30. package/autoresearch/save-adapters/xhs-note-comments.ts +61 -0
  31. package/autoresearch/save-adapters/xhs-search-full.ts +62 -0
  32. package/autoresearch/save-adapters/zhihu-hot-detail.ts +52 -0
  33. package/autoresearch/save-adapters/zhihu-question-full.ts +57 -0
  34. package/autoresearch/save-adapters/zhihu-search-detail.ts +53 -0
  35. package/autoresearch/save-tasks.json +281 -0
  36. package/autoresearch/v2ex-tasks.json +899 -0
  37. package/autoresearch/zhihu-tasks.json +848 -0
  38. package/bun.lock +615 -0
  39. package/dist/browser/base-page.d.ts +4 -2
  40. package/dist/browser/base-page.js +37 -4
  41. package/dist/browser/bridge.js +10 -8
  42. package/dist/browser/cdp.js +2 -6
  43. package/dist/browser/daemon-client.d.ts +11 -1
  44. package/dist/browser/daemon-client.js +3 -0
  45. package/dist/browser/dom-helpers.d.ts +4 -2
  46. package/dist/browser/dom-helpers.js +42 -31
  47. package/dist/browser/dom-snapshot.js +23 -1
  48. package/dist/browser/page.d.ts +7 -2
  49. package/dist/browser/page.js +112 -30
  50. package/dist/browser.test.js +1 -1
  51. package/dist/build-manifest.d.ts +1 -0
  52. package/dist/build-manifest.js +1 -0
  53. package/dist/cli-manifest.json +1133 -182
  54. package/dist/cli.d.ts +2 -0
  55. package/dist/cli.js +48 -7
  56. package/dist/cli.test.d.ts +1 -0
  57. package/dist/cli.test.js +88 -0
  58. package/dist/clis/1688/item.d.ts +70 -0
  59. package/dist/clis/1688/item.js +187 -0
  60. package/dist/clis/1688/item.test.d.ts +1 -0
  61. package/dist/clis/1688/item.test.js +67 -0
  62. package/dist/clis/1688/search.d.ts +56 -0
  63. package/dist/clis/1688/search.js +309 -0
  64. package/dist/clis/1688/search.test.d.ts +1 -0
  65. package/dist/clis/1688/search.test.js +75 -0
  66. package/dist/clis/1688/shared.d.ts +112 -0
  67. package/dist/clis/1688/shared.js +514 -0
  68. package/dist/clis/1688/shared.test.d.ts +1 -0
  69. package/dist/clis/1688/shared.test.js +57 -0
  70. package/dist/clis/1688/store.d.ts +45 -0
  71. package/dist/clis/1688/store.js +226 -0
  72. package/dist/clis/1688/store.test.d.ts +1 -0
  73. package/dist/clis/1688/store.test.js +62 -0
  74. package/dist/clis/amazon/bestsellers.d.ts +0 -20
  75. package/dist/clis/amazon/bestsellers.js +6 -129
  76. package/dist/clis/amazon/bestsellers.test.js +12 -3
  77. package/dist/clis/amazon/movers-shakers.d.ts +1 -0
  78. package/dist/clis/amazon/movers-shakers.js +7 -0
  79. package/dist/clis/amazon/new-releases.d.ts +1 -0
  80. package/dist/clis/amazon/new-releases.js +7 -0
  81. package/dist/clis/amazon/rankings.d.ts +59 -0
  82. package/dist/clis/amazon/rankings.js +226 -0
  83. package/dist/clis/amazon/rankings.test.d.ts +1 -0
  84. package/dist/clis/amazon/rankings.test.js +41 -0
  85. package/dist/clis/amazon/shared.d.ts +11 -0
  86. package/dist/clis/amazon/shared.js +121 -11
  87. package/dist/clis/amazon/shared.test.js +11 -0
  88. package/dist/clis/bilibili/comments.js +2 -2
  89. package/dist/clis/bilibili/comments.test.js +3 -2
  90. package/dist/clis/bilibili/download.js +2 -1
  91. package/dist/clis/bilibili/subtitle.js +4 -3
  92. package/dist/clis/bilibili/subtitle.test.js +2 -1
  93. package/dist/clis/bilibili/utils.d.ts +5 -0
  94. package/dist/clis/bilibili/utils.js +30 -0
  95. package/dist/clis/bilibili/utils.test.d.ts +1 -0
  96. package/dist/clis/bilibili/utils.test.js +17 -0
  97. package/dist/clis/douban/marks.js +1 -1
  98. package/dist/clis/douban/subject.yaml +50 -19
  99. package/dist/clis/doubao/utils.js +32 -12
  100. package/dist/clis/douyin/_shared/browser-fetch.test.js +0 -1
  101. package/dist/clis/douyin/_shared/transcode.test.js +0 -2
  102. package/dist/clis/douyin/draft.test.js +0 -2
  103. package/dist/clis/facebook/search.test.js +0 -2
  104. package/dist/clis/gemini/ask.js +9 -3
  105. package/dist/clis/gemini/ask.test.d.ts +1 -0
  106. package/dist/clis/gemini/ask.test.js +100 -0
  107. package/dist/clis/gemini/reply-state.test.d.ts +1 -0
  108. package/dist/clis/gemini/reply-state.test.js +641 -0
  109. package/dist/clis/gemini/utils.d.ts +44 -1
  110. package/dist/clis/gemini/utils.js +528 -61
  111. package/dist/clis/gemini/utils.test.js +149 -2
  112. package/dist/clis/hupu/detail.d.ts +1 -0
  113. package/dist/clis/hupu/detail.js +72 -0
  114. package/dist/clis/hupu/hot.yaml +43 -0
  115. package/dist/clis/hupu/like.d.ts +1 -0
  116. package/dist/clis/hupu/like.js +75 -0
  117. package/dist/clis/hupu/reply.d.ts +1 -0
  118. package/dist/clis/hupu/reply.js +71 -0
  119. package/dist/clis/hupu/search.d.ts +1 -0
  120. package/dist/clis/hupu/search.js +59 -0
  121. package/dist/clis/hupu/unlike.d.ts +1 -0
  122. package/dist/clis/hupu/unlike.js +75 -0
  123. package/dist/clis/hupu/utils.d.ts +20 -0
  124. package/dist/clis/hupu/utils.js +319 -0
  125. package/dist/clis/instagram/_shared/private-publish.d.ts +138 -0
  126. package/dist/clis/instagram/_shared/private-publish.js +1030 -0
  127. package/dist/clis/instagram/_shared/private-publish.test.d.ts +1 -0
  128. package/dist/clis/instagram/_shared/private-publish.test.js +705 -0
  129. package/dist/clis/instagram/_shared/protocol-capture.d.ts +26 -0
  130. package/dist/clis/instagram/_shared/protocol-capture.js +282 -0
  131. package/dist/clis/instagram/_shared/protocol-capture.test.d.ts +1 -0
  132. package/dist/clis/instagram/_shared/protocol-capture.test.js +114 -0
  133. package/dist/clis/instagram/_shared/runtime-info.d.ts +9 -0
  134. package/dist/clis/instagram/_shared/runtime-info.js +81 -0
  135. package/dist/clis/instagram/note.d.ts +1 -0
  136. package/dist/clis/instagram/note.js +222 -0
  137. package/dist/clis/instagram/note.test.d.ts +1 -0
  138. package/dist/clis/instagram/note.test.js +81 -0
  139. package/dist/clis/instagram/post.d.ts +4 -0
  140. package/dist/clis/instagram/post.js +1496 -0
  141. package/dist/clis/instagram/post.test.d.ts +1 -0
  142. package/dist/clis/instagram/post.test.js +1647 -0
  143. package/dist/clis/instagram/reel.d.ts +1 -0
  144. package/dist/clis/instagram/reel.js +826 -0
  145. package/dist/clis/instagram/reel.test.d.ts +1 -0
  146. package/dist/clis/instagram/reel.test.js +167 -0
  147. package/dist/clis/instagram/story.d.ts +1 -0
  148. package/dist/clis/instagram/story.js +115 -0
  149. package/dist/clis/instagram/story.test.d.ts +1 -0
  150. package/dist/clis/instagram/story.test.js +167 -0
  151. package/dist/clis/sinafinance/stock-rank.d.ts +4 -0
  152. package/dist/clis/sinafinance/stock-rank.js +65 -0
  153. package/dist/clis/substack/utils.test.js +0 -2
  154. package/dist/clis/twitter/post.js +72 -45
  155. package/dist/clis/twitter/post.test.d.ts +1 -0
  156. package/dist/clis/twitter/post.test.js +116 -0
  157. package/dist/clis/twitter/reply.d.ts +12 -0
  158. package/dist/clis/twitter/reply.js +257 -35
  159. package/dist/clis/twitter/reply.test.d.ts +1 -0
  160. package/dist/clis/twitter/reply.test.js +151 -0
  161. package/dist/clis/twitter/search.js +67 -5
  162. package/dist/clis/twitter/search.test.js +83 -5
  163. package/dist/clis/xianyu/chat.d.ts +7 -0
  164. package/dist/clis/xianyu/chat.js +146 -0
  165. package/dist/clis/xianyu/chat.test.d.ts +1 -0
  166. package/dist/clis/xianyu/chat.test.js +15 -0
  167. package/dist/clis/xianyu/item.d.ts +7 -0
  168. package/dist/clis/xianyu/item.js +152 -0
  169. package/dist/clis/xianyu/item.test.d.ts +1 -0
  170. package/dist/clis/xianyu/item.test.js +56 -0
  171. package/dist/clis/xianyu/search.d.ts +10 -0
  172. package/dist/clis/xianyu/search.js +134 -0
  173. package/dist/clis/xianyu/search.test.d.ts +1 -0
  174. package/dist/clis/xianyu/search.test.js +17 -0
  175. package/dist/clis/xianyu/utils.d.ts +1 -0
  176. package/dist/clis/xianyu/utils.js +8 -0
  177. package/dist/clis/xiaoe/catalog.yaml +129 -0
  178. package/dist/clis/xiaoe/content.yaml +43 -0
  179. package/dist/clis/xiaoe/courses.yaml +73 -0
  180. package/dist/clis/xiaoe/detail.yaml +39 -0
  181. package/dist/clis/xiaoe/play-url.yaml +124 -0
  182. package/dist/clis/xiaohongshu/comments.test.js +0 -2
  183. package/dist/clis/xiaohongshu/creator-note-detail.test.js +0 -2
  184. package/dist/clis/xiaohongshu/creator-notes.test.js +0 -2
  185. package/dist/clis/xiaohongshu/download.test.js +0 -2
  186. package/dist/clis/xiaohongshu/note.test.js +0 -2
  187. package/dist/clis/xiaohongshu/publish.test.js +0 -2
  188. package/dist/clis/xiaohongshu/search.js +29 -20
  189. package/dist/clis/xiaohongshu/search.test.js +56 -48
  190. package/dist/clis/yuanbao/ask.d.ts +21 -0
  191. package/dist/clis/yuanbao/ask.js +427 -0
  192. package/dist/clis/yuanbao/ask.test.d.ts +1 -0
  193. package/dist/clis/yuanbao/ask.test.js +124 -0
  194. package/dist/clis/yuanbao/new.d.ts +1 -0
  195. package/dist/clis/yuanbao/new.js +70 -0
  196. package/dist/clis/yuanbao/new.test.d.ts +1 -0
  197. package/dist/clis/yuanbao/new.test.js +30 -0
  198. package/dist/clis/yuanbao/shared.d.ts +13 -0
  199. package/dist/clis/yuanbao/shared.js +49 -0
  200. package/dist/clis/zhihu/question.js +30 -19
  201. package/dist/clis/zhihu/question.test.js +34 -16
  202. package/dist/commanderAdapter.js +8 -4
  203. package/dist/commanderAdapter.test.js +42 -0
  204. package/dist/completion.js +3 -1
  205. package/dist/completion.test.d.ts +1 -0
  206. package/dist/completion.test.js +23 -0
  207. package/dist/doctor.js +1 -1
  208. package/dist/electron-apps.d.ts +2 -0
  209. package/dist/electron-apps.js +7 -1
  210. package/dist/errors.js +1 -1
  211. package/dist/execution.js +25 -35
  212. package/dist/explore.js +1 -1
  213. package/dist/launcher.d.ts +4 -0
  214. package/dist/launcher.js +64 -8
  215. package/dist/launcher.test.js +88 -7
  216. package/dist/output.d.ts +2 -0
  217. package/dist/output.js +10 -1
  218. package/dist/output.test.d.ts +0 -3
  219. package/dist/output.test.js +59 -92
  220. package/dist/pipeline/executor.test.js +0 -2
  221. package/dist/pipeline/steps/download.test.js +0 -2
  222. package/dist/registry.d.ts +2 -0
  223. package/dist/serialization.d.ts +1 -0
  224. package/dist/serialization.js +1 -0
  225. package/dist/types.d.ts +9 -2
  226. package/docs/.vitepress/config.mts +4 -0
  227. package/docs/adapters/browser/1688.md +52 -0
  228. package/docs/adapters/browser/36kr.md +2 -1
  229. package/docs/adapters/browser/doubao.md +5 -1
  230. package/docs/adapters/browser/hupu.md +53 -0
  231. package/docs/adapters/browser/sinafinance.md +32 -2
  232. package/docs/adapters/browser/weibo.md +6 -1
  233. package/docs/adapters/browser/wikipedia.md +2 -0
  234. package/docs/adapters/browser/xianyu.md +42 -0
  235. package/docs/adapters/browser/xiaoe.md +44 -0
  236. package/docs/adapters/browser/yuanbao.md +64 -0
  237. package/docs/adapters/index.md +14 -5
  238. package/docs/comparison.md +1 -1
  239. package/docs/developer/ai-workflow.md +2 -2
  240. package/docs/developer/contributing.md +1 -1
  241. package/docs/developer/testing.md +2 -0
  242. package/docs/guide/plugins.md +1 -0
  243. package/docs/guide/troubleshooting.md +11 -0
  244. package/docs/superpowers/specs/2026-04-03-v2ex-autoresearch-design.md +41 -0
  245. package/docs/zh/guide/plugins.md +1 -0
  246. package/extension/dist/background.js +1127 -0
  247. package/extension/src/background.test.ts +39 -0
  248. package/extension/src/background.ts +223 -34
  249. package/extension/src/cdp.ts +194 -4
  250. package/extension/src/protocol.ts +22 -1
  251. package/package.json +3 -2
  252. package/scripts/postinstall.js +1 -1
  253. package/skills/opencli-explorer/SKILL.md +1 -1
  254. package/skills/opencli-oneshot/SKILL.md +2 -2
  255. package/skills/opencli-operate/SKILL.md +120 -27
  256. package/skills/opencli-usage/SKILL.md +31 -20
  257. package/skills/opencli-usage/browser.md +114 -16
  258. package/skills/opencli-usage/public-api.md +32 -3
  259. package/skills/smart-search/SKILL.md +156 -0
  260. package/skills/smart-search/references/sources-ai.md +74 -0
  261. package/skills/smart-search/references/sources-info.md +43 -0
  262. package/skills/smart-search/references/sources-media.md +50 -0
  263. package/skills/smart-search/references/sources-other.md +42 -0
  264. package/skills/smart-search/references/sources-shopping.md +31 -0
  265. package/skills/smart-search/references/sources-social.md +51 -0
  266. package/skills/smart-search/references/sources-tech.md +42 -0
  267. package/skills/smart-search/references/sources-travel.md +20 -0
  268. package/src/browser/base-page.ts +41 -6
  269. package/src/browser/bridge.ts +11 -8
  270. package/src/browser/cdp.ts +1 -8
  271. package/src/browser/daemon-client.ts +11 -1
  272. package/src/browser/dom-helpers.ts +43 -31
  273. package/src/browser/dom-snapshot.ts +23 -1
  274. package/src/browser/page.ts +115 -31
  275. package/src/browser.test.ts +1 -1
  276. package/src/build-manifest.ts +2 -0
  277. package/src/cli.test.ts +133 -0
  278. package/src/cli.ts +73 -11
  279. package/src/clis/1688/item.test.ts +69 -0
  280. package/src/clis/1688/item.ts +282 -0
  281. package/src/clis/1688/search.test.ts +81 -0
  282. package/src/clis/1688/search.ts +402 -0
  283. package/src/clis/1688/shared.test.ts +75 -0
  284. package/src/clis/1688/shared.ts +623 -0
  285. package/src/clis/1688/store.test.ts +69 -0
  286. package/src/clis/1688/store.ts +300 -0
  287. package/src/clis/amazon/bestsellers.test.ts +12 -3
  288. package/src/clis/amazon/bestsellers.ts +6 -178
  289. package/src/clis/amazon/movers-shakers.ts +8 -0
  290. package/src/clis/amazon/new-releases.ts +8 -0
  291. package/src/clis/amazon/rankings.test.ts +47 -0
  292. package/src/clis/amazon/rankings.ts +312 -0
  293. package/src/clis/amazon/shared.test.ts +16 -0
  294. package/src/clis/amazon/shared.ts +134 -12
  295. package/src/clis/bilibili/comments.test.ts +4 -3
  296. package/src/clis/bilibili/comments.ts +2 -2
  297. package/src/clis/bilibili/download.ts +2 -1
  298. package/src/clis/bilibili/subtitle.test.ts +2 -1
  299. package/src/clis/bilibili/subtitle.ts +4 -3
  300. package/src/clis/bilibili/utils.test.ts +21 -0
  301. package/src/clis/bilibili/utils.ts +27 -0
  302. package/src/clis/douban/marks.ts +1 -1
  303. package/src/clis/douban/subject.yaml +50 -19
  304. package/src/clis/doubao/utils.ts +32 -12
  305. package/src/clis/douyin/_shared/browser-fetch.test.ts +0 -1
  306. package/src/clis/douyin/_shared/transcode.test.ts +0 -2
  307. package/src/clis/douyin/draft.test.ts +0 -2
  308. package/src/clis/facebook/search.test.ts +0 -2
  309. package/src/clis/gemini/ask.test.ts +116 -0
  310. package/src/clis/gemini/ask.ts +10 -3
  311. package/src/clis/gemini/reply-state.test.ts +708 -0
  312. package/src/clis/gemini/utils.test.ts +184 -2
  313. package/src/clis/gemini/utils.ts +588 -60
  314. package/src/clis/hupu/detail.ts +126 -0
  315. package/src/clis/hupu/hot.yaml +43 -0
  316. package/src/clis/hupu/like.ts +76 -0
  317. package/src/clis/hupu/reply.ts +76 -0
  318. package/src/clis/hupu/search.ts +95 -0
  319. package/src/clis/hupu/unlike.ts +76 -0
  320. package/src/clis/hupu/utils.ts +381 -0
  321. package/src/clis/instagram/_shared/private-publish.test.ts +827 -0
  322. package/src/clis/instagram/_shared/private-publish.ts +1303 -0
  323. package/src/clis/instagram/_shared/protocol-capture.test.ts +148 -0
  324. package/src/clis/instagram/_shared/protocol-capture.ts +321 -0
  325. package/src/clis/instagram/_shared/runtime-info.ts +91 -0
  326. package/src/clis/instagram/note.test.ts +96 -0
  327. package/src/clis/instagram/note.ts +254 -0
  328. package/src/clis/instagram/post.test.ts +1716 -0
  329. package/src/clis/instagram/post.ts +1620 -0
  330. package/src/clis/instagram/reel.test.ts +191 -0
  331. package/src/clis/instagram/reel.ts +886 -0
  332. package/src/clis/instagram/story.test.ts +191 -0
  333. package/src/clis/instagram/story.ts +151 -0
  334. package/src/clis/sinafinance/stock-rank.ts +68 -0
  335. package/src/clis/substack/utils.test.ts +0 -2
  336. package/src/clis/twitter/post.test.ts +157 -0
  337. package/src/clis/twitter/post.ts +82 -48
  338. package/src/clis/twitter/reply.test.ts +177 -0
  339. package/src/clis/twitter/reply.ts +285 -39
  340. package/src/clis/twitter/search.test.ts +88 -5
  341. package/src/clis/twitter/search.ts +68 -5
  342. package/src/clis/xianyu/chat.test.ts +20 -0
  343. package/src/clis/xianyu/chat.ts +175 -0
  344. package/src/clis/xianyu/item.test.ts +67 -0
  345. package/src/clis/xianyu/item.ts +172 -0
  346. package/src/clis/xianyu/search.test.ts +22 -0
  347. package/src/clis/xianyu/search.ts +151 -0
  348. package/src/clis/xianyu/utils.ts +9 -0
  349. package/src/clis/xiaoe/catalog.yaml +129 -0
  350. package/src/clis/xiaoe/content.yaml +43 -0
  351. package/src/clis/xiaoe/courses.yaml +73 -0
  352. package/src/clis/xiaoe/detail.yaml +39 -0
  353. package/src/clis/xiaoe/play-url.yaml +124 -0
  354. package/src/clis/xiaohongshu/comments.test.ts +0 -2
  355. package/src/clis/xiaohongshu/creator-note-detail.test.ts +0 -2
  356. package/src/clis/xiaohongshu/creator-notes.test.ts +0 -2
  357. package/src/clis/xiaohongshu/download.test.ts +0 -2
  358. package/src/clis/xiaohongshu/note.test.ts +0 -2
  359. package/src/clis/xiaohongshu/publish.test.ts +0 -2
  360. package/src/clis/xiaohongshu/search.test.ts +59 -48
  361. package/src/clis/xiaohongshu/search.ts +31 -21
  362. package/src/clis/yuanbao/ask.test.ts +156 -0
  363. package/src/clis/yuanbao/ask.ts +522 -0
  364. package/src/clis/yuanbao/new.test.ts +36 -0
  365. package/src/clis/yuanbao/new.ts +81 -0
  366. package/src/clis/yuanbao/shared.ts +57 -0
  367. package/src/clis/zhihu/question.test.ts +42 -17
  368. package/src/clis/zhihu/question.ts +31 -26
  369. package/src/commanderAdapter.test.ts +51 -0
  370. package/src/commanderAdapter.ts +8 -4
  371. package/src/completion.test.ts +30 -0
  372. package/src/completion.ts +3 -1
  373. package/src/doctor.ts +1 -1
  374. package/src/electron-apps.ts +9 -1
  375. package/src/errors.ts +1 -1
  376. package/src/execution.ts +26 -30
  377. package/src/explore.ts +1 -1
  378. package/src/launcher.test.ts +121 -7
  379. package/src/launcher.ts +87 -9
  380. package/src/output.test.ts +50 -90
  381. package/src/output.ts +10 -1
  382. package/src/pipeline/executor.test.ts +0 -2
  383. package/src/pipeline/steps/download.test.ts +0 -2
  384. package/src/registry.ts +2 -0
  385. package/src/serialization.ts +2 -0
  386. package/src/types.ts +9 -2
  387. package/tests/e2e/browser-auth.test.ts +9 -0
  388. package/CLI-EXPLORER.md +0 -724
  389. package/CLI-ONESHOT.md +0 -216
  390. package/SKILL.md +0 -59
@@ -0,0 +1,359 @@
1
+ /**
2
+ * AutoResearch Engine — Karpathy's 8-phase autonomous iteration loop.
3
+ *
4
+ * Phase 0: Precondition checks (git clean, no locks)
5
+ * Phase 1: Review (read scope files + log + git history)
6
+ * Phase 2: Ideate (select next change based on history)
7
+ * Phase 3: Modify (one atomic change — delegated to caller)
8
+ * Phase 4: Commit (git add + commit with experiment prefix)
9
+ * Phase 5: Verify (run verify command, extract metric)
10
+ * Phase 5.5: Guard (optional regression check)
11
+ * Phase 6: Decide (keep/discard/crash + rollback)
12
+ * Phase 7: Log (append TSV)
13
+ * Phase 8: Repeat
14
+ */
15
+
16
+ import { execSync } from 'node:child_process';
17
+ import { readFileSync, existsSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { type AutoResearchConfig, type IterationResult, type IterationStatus, extractMetric } from './config.js';
20
+ import { Logger } from './logger.js';
21
+
22
+ export interface EngineCallbacks {
23
+ /** Called at Phase 2-3: review context, ideate, and make ONE change.
24
+ * Return a one-sentence description of what was changed, or null to skip. */
25
+ modify(context: ModifyContext): Promise<string | null>;
26
+
27
+ /** Called when engine needs to report status */
28
+ onStatus?(msg: string): void;
29
+ }
30
+
31
+ export interface ModifyContext {
32
+ iteration: number;
33
+ bestMetric: number;
34
+ currentMetric: number;
35
+ recentLog: IterationResult[];
36
+ gitLog: string;
37
+ scopeFiles: string[];
38
+ consecutiveDiscards: number;
39
+ stuckHint: string | null;
40
+ }
41
+
42
+ const ROOT = join(import.meta.dirname ?? process.cwd(), '..');
43
+
44
+ function exec(cmd: string, opts?: { timeout?: number; cwd?: string }): string {
45
+ try {
46
+ return execSync(cmd, {
47
+ cwd: opts?.cwd ?? ROOT,
48
+ timeout: opts?.timeout ?? 120_000,
49
+ encoding: 'utf-8',
50
+ stdio: ['pipe', 'pipe', 'pipe'],
51
+ env: process.env,
52
+ }).trim();
53
+ } catch (err: any) {
54
+ return err.stdout?.trim() ?? err.message ?? '';
55
+ }
56
+ }
57
+
58
+ function execStrict(cmd: string, opts?: { timeout?: number }): string {
59
+ return execSync(cmd, {
60
+ cwd: ROOT,
61
+ timeout: opts?.timeout ?? 120_000,
62
+ encoding: 'utf-8',
63
+ stdio: ['pipe', 'pipe', 'pipe'],
64
+ env: process.env,
65
+ }).trim();
66
+ }
67
+
68
+ export class Engine {
69
+ private config: AutoResearchConfig;
70
+ private logger: Logger;
71
+ private callbacks: EngineCallbacks;
72
+ private bestMetric: number = 0;
73
+ private currentMetric: number = 0;
74
+ private iteration: number = 0;
75
+
76
+ constructor(config: AutoResearchConfig, logPath: string, callbacks: EngineCallbacks) {
77
+ this.config = config;
78
+ this.logger = new Logger(logPath);
79
+ this.callbacks = callbacks;
80
+ }
81
+
82
+ private log(msg: string): void {
83
+ this.callbacks.onStatus?.(msg);
84
+ }
85
+
86
+ /** Phase 0: Precondition checks */
87
+ private checkPreconditions(): void {
88
+ // Git repo exists
89
+ try { execStrict('git rev-parse --git-dir'); }
90
+ catch { throw new Error('Not a git repository'); }
91
+
92
+ // Clean working tree
93
+ const status = exec('git status --porcelain');
94
+ if (status) throw new Error(`Working tree not clean:\n${status}`);
95
+
96
+ // No stale locks
97
+ if (existsSync(join(ROOT, '.git', 'index.lock'))) {
98
+ throw new Error('Stale .git/index.lock found — remove it first');
99
+ }
100
+
101
+ // Not detached HEAD
102
+ try { execStrict('git symbolic-ref HEAD'); }
103
+ catch { throw new Error('Detached HEAD — checkout a branch first'); }
104
+ }
105
+
106
+ /** Phase 5: Run verify command and extract metric */
107
+ private runVerify(): number | null {
108
+ this.log(' verify...');
109
+ const output = exec(this.config.verify, { timeout: 300_000 });
110
+ return extractMetric(output);
111
+ }
112
+
113
+ /** Phase 5.5: Run guard command */
114
+ private runGuard(): boolean {
115
+ if (!this.config.guard) return true;
116
+ this.log(' guard...');
117
+ try {
118
+ execStrict(this.config.guard, { timeout: 300_000 });
119
+ return true;
120
+ } catch {
121
+ return false;
122
+ }
123
+ }
124
+
125
+ /** Phase 4: Commit changes */
126
+ private commit(description: string): string | null {
127
+ // Stage all changes in scope (but not untracked outside scope)
128
+ exec('git add -A');
129
+ const diff = exec('git diff --cached --quiet; echo $?');
130
+ if (diff === '0') return null; // no changes
131
+
132
+ try {
133
+ execStrict(`git commit -m "experiment(operate): ${description.replace(/"/g, '\\"')}"`);
134
+ return exec('git rev-parse --short HEAD');
135
+ } catch {
136
+ // Hook failure
137
+ exec('git reset HEAD');
138
+ return 'hook-blocked';
139
+ }
140
+ }
141
+
142
+ /** Phase 6: Rollback */
143
+ private safeRevert(): void {
144
+ try {
145
+ execStrict('git revert HEAD --no-edit');
146
+ } catch {
147
+ exec('git revert --abort');
148
+ exec('git reset --hard HEAD~1');
149
+ }
150
+ }
151
+
152
+ /** Get stuck hint when >5 consecutive discards */
153
+ private getStuckHint(discards: number): string | null {
154
+ if (discards < 5) return null;
155
+ const hints = [
156
+ 'Re-read ALL scope files from scratch. Try a completely different approach.',
157
+ 'Review entire results log — what worked before? Try combining successful changes.',
158
+ 'Try the OPPOSITE of what has been failing.',
159
+ 'Try a radical architectural change instead of incremental tweaks.',
160
+ 'Simplify — remove complexity rather than adding it.',
161
+ ];
162
+ return hints[Math.min(discards - 5, hints.length - 1)];
163
+ }
164
+
165
+ /** Run the main loop */
166
+ async run(): Promise<IterationResult[]> {
167
+ const results: IterationResult[] = [];
168
+
169
+ // Phase 0: Preconditions
170
+ this.log('Phase 0: Precondition checks...');
171
+ this.checkPreconditions();
172
+
173
+ // Initialize logger
174
+ this.logger.init(this.config);
175
+
176
+ // Baseline measurement
177
+ this.log('Measuring baseline...');
178
+ const baseline = this.runVerify();
179
+ if (baseline == null) throw new Error('Verify command returned no metric for baseline');
180
+ this.bestMetric = baseline;
181
+ this.currentMetric = baseline;
182
+
183
+ const baselineCommit = exec('git rev-parse --short HEAD');
184
+ const baselineResult: IterationResult = {
185
+ iteration: 0,
186
+ commit: baselineCommit,
187
+ metric: baseline,
188
+ delta: 0,
189
+ guard: this.config.guard ? (this.runGuard() ? 'pass' : 'fail') : '-',
190
+ status: 'baseline',
191
+ description: `initial state — ${this.config.metric} ${baseline}`,
192
+ };
193
+ this.logger.append(baselineResult);
194
+ results.push(baselineResult);
195
+ this.log(`Baseline: ${this.config.metric} = ${baseline}`);
196
+
197
+ // Main loop
198
+ const maxIter = this.config.iterations ?? Infinity;
199
+ for (this.iteration = 1; this.iteration <= maxIter; this.iteration++) {
200
+ this.log(`\n━━━ Iteration ${this.iteration}${maxIter < Infinity ? `/${maxIter}` : ''} ━━━`);
201
+
202
+ // Phase 1: Review
203
+ const gitLog = exec('git log --oneline -20');
204
+ const recentLog = this.logger.readLast(20);
205
+ const scopeFiles = this.config.scope;
206
+ const consecutiveDiscards = this.logger.consecutiveDiscards();
207
+
208
+ // Phase 2-3: Ideate + Modify (delegated to callback)
209
+ const context: ModifyContext = {
210
+ iteration: this.iteration,
211
+ bestMetric: this.bestMetric,
212
+ currentMetric: this.currentMetric,
213
+ recentLog,
214
+ gitLog,
215
+ scopeFiles,
216
+ consecutiveDiscards,
217
+ stuckHint: this.getStuckHint(consecutiveDiscards),
218
+ };
219
+
220
+ let description: string | null;
221
+ try {
222
+ description = await this.callbacks.modify(context);
223
+ } catch (err: any) {
224
+ this.log(` modify error: ${err.message}`);
225
+ const result: IterationResult = {
226
+ iteration: this.iteration,
227
+ commit: '-',
228
+ metric: this.currentMetric,
229
+ delta: 0,
230
+ guard: '-',
231
+ status: 'crash',
232
+ description: `modify crashed: ${err.message?.slice(0, 80)}`,
233
+ };
234
+ this.logger.append(result);
235
+ results.push(result);
236
+ continue;
237
+ }
238
+
239
+ if (!description) {
240
+ const result: IterationResult = {
241
+ iteration: this.iteration,
242
+ commit: '-',
243
+ metric: this.currentMetric,
244
+ delta: 0,
245
+ guard: '-',
246
+ status: 'no-op',
247
+ description: 'no changes made',
248
+ };
249
+ this.logger.append(result);
250
+ results.push(result);
251
+ continue;
252
+ }
253
+
254
+ // Phase 4: Commit
255
+ this.log(` commit: ${description}`);
256
+ const commitHash = this.commit(description);
257
+ if (!commitHash) {
258
+ const result: IterationResult = {
259
+ iteration: this.iteration,
260
+ commit: '-',
261
+ metric: this.currentMetric,
262
+ delta: 0,
263
+ guard: '-',
264
+ status: 'no-op',
265
+ description: `no diff after: ${description}`,
266
+ };
267
+ this.logger.append(result);
268
+ results.push(result);
269
+ continue;
270
+ }
271
+ if (commitHash === 'hook-blocked') {
272
+ const result: IterationResult = {
273
+ iteration: this.iteration,
274
+ commit: '-',
275
+ metric: this.currentMetric,
276
+ delta: 0,
277
+ guard: '-',
278
+ status: 'hook-blocked',
279
+ description: `hook rejected: ${description}`,
280
+ };
281
+ this.logger.append(result);
282
+ results.push(result);
283
+ continue;
284
+ }
285
+
286
+ // Phase 5: Verify
287
+ const metric = this.runVerify();
288
+ if (metric == null) {
289
+ this.log(' verify crashed — reverting');
290
+ this.safeRevert();
291
+ const result: IterationResult = {
292
+ iteration: this.iteration,
293
+ commit: '-',
294
+ metric: this.currentMetric,
295
+ delta: 0,
296
+ guard: '-',
297
+ status: 'crash',
298
+ description: `verify crashed: ${description}`,
299
+ };
300
+ this.logger.append(result);
301
+ results.push(result);
302
+ continue;
303
+ }
304
+
305
+ const improved = this.config.direction === 'higher'
306
+ ? metric > this.bestMetric
307
+ : metric < this.bestMetric;
308
+ const delta = +(metric - this.bestMetric).toFixed(4);
309
+ const absDelta = Math.abs(delta);
310
+ const minDelta = this.config.minDelta ?? 0;
311
+
312
+ // Phase 5.5: Guard
313
+ let guardResult: 'pass' | 'fail' | '-' = '-';
314
+ if (this.config.guard && improved && absDelta >= minDelta) {
315
+ guardResult = this.runGuard() ? 'pass' : 'fail';
316
+ }
317
+
318
+ // Phase 6: Decide
319
+ let status: IterationStatus;
320
+ if (improved && absDelta >= minDelta && (guardResult !== 'fail')) {
321
+ status = 'keep';
322
+ this.bestMetric = metric;
323
+ this.currentMetric = metric;
324
+ this.log(` ✓ KEEP — ${this.config.metric}: ${metric} (${delta >= 0 ? '+' : ''}${delta})`);
325
+ } else if (improved && guardResult === 'fail') {
326
+ this.log(' guard failed — reverting');
327
+ this.safeRevert();
328
+ status = 'discard';
329
+ this.log(` ✗ DISCARD (guard) — ${description}`);
330
+ } else {
331
+ this.safeRevert();
332
+ status = 'discard';
333
+ const reason = absDelta < minDelta ? 'below min delta' : 'no improvement';
334
+ this.log(` ✗ DISCARD (${reason}) — ${this.config.metric}: ${metric} (${delta >= 0 ? '+' : ''}${delta})`);
335
+ }
336
+
337
+ const result: IterationResult = {
338
+ iteration: this.iteration,
339
+ commit: status === 'keep' ? commitHash : '-',
340
+ metric,
341
+ delta,
342
+ guard: guardResult,
343
+ status,
344
+ description,
345
+ };
346
+ this.logger.append(result);
347
+ results.push(result);
348
+ }
349
+
350
+ // Summary
351
+ const keeps = results.filter(r => r.status === 'keep' || r.status === 'keep (reworked)');
352
+ const discards = results.filter(r => r.status === 'discard');
353
+ this.log(`\n${'━'.repeat(50)}`);
354
+ this.log(`Done: ${this.iteration - 1} iterations, ${keeps.length} kept, ${discards.length} discarded`);
355
+ this.log(`Final ${this.config.metric}: ${this.bestMetric} (started at ${results[0]?.metric})`);
356
+
357
+ return results;
358
+ }
359
+ }
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Combined Test Suite Runner — runs browse + V2EX + Zhihu tasks.
4
+ * Reports combined score for AutoResearch iteration.
5
+ *
6
+ * Usage:
7
+ * npx tsx autoresearch/eval-all.ts # Run all
8
+ * npx tsx autoresearch/eval-all.ts --suite v2ex # Run one suite
9
+ */
10
+
11
+ import { execSync } from 'node:child_process';
12
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
13
+ import { join, dirname } from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const ROOT = join(__dirname, '..');
18
+ const RESULTS_DIR = join(__dirname, 'results');
19
+
20
+ interface SuiteResult {
21
+ name: string;
22
+ passed: number;
23
+ total: number;
24
+ failures: string[];
25
+ duration: number;
26
+ }
27
+
28
+ function runSuite(name: string, script: string): SuiteResult {
29
+ const start = Date.now();
30
+ try {
31
+ const output = execSync(`npx tsx ${script}`, {
32
+ cwd: ROOT,
33
+ timeout: 600_000,
34
+ encoding: 'utf-8',
35
+ env: process.env,
36
+ stdio: ['pipe', 'pipe', 'pipe'],
37
+ });
38
+
39
+ // Parse SCORE=X/Y from output
40
+ const scoreMatch = output.match(/SCORE=(\d+)\/(\d+)/);
41
+ const passed = scoreMatch ? parseInt(scoreMatch[1], 10) : 0;
42
+ const total = scoreMatch ? parseInt(scoreMatch[2], 10) : 0;
43
+
44
+ // Parse failures
45
+ const failures: string[] = [];
46
+ const failLines = output.match(/✗.*$/gm) || [];
47
+ for (const line of failLines) {
48
+ const m = line.match(/✗\s+(?:\[.*?\]\s+)?(\S+)/);
49
+ if (m) failures.push(m[1].replace(/:$/, ''));
50
+ }
51
+
52
+ return { name, passed, total, failures, duration: Date.now() - start };
53
+ } catch (err: any) {
54
+ const output = err.stdout ?? '';
55
+ const scoreMatch = output.match(/SCORE=(\d+)\/(\d+)/);
56
+ const passed = scoreMatch ? parseInt(scoreMatch[1], 10) : 0;
57
+ const total = scoreMatch ? parseInt(scoreMatch[2], 10) : 0;
58
+ const failures: string[] = [];
59
+ const failLines = output.match(/✗.*$/gm) || [];
60
+ for (const line of failLines) {
61
+ const m = line.match(/✗\s+(?:\[.*?\]\s+)?(\S+)/);
62
+ if (m) failures.push(m[1].replace(/:$/, ''));
63
+ }
64
+ return { name, passed, total, failures, duration: Date.now() - start };
65
+ }
66
+ }
67
+
68
+ function main() {
69
+ const args = process.argv.slice(2);
70
+ const singleSuite = args.includes('--suite') ? args[args.indexOf('--suite') + 1] : null;
71
+
72
+ const suites = [
73
+ { name: 'browse', script: 'autoresearch/eval-browse.ts' },
74
+ { name: 'v2ex', script: 'autoresearch/eval-v2ex.ts' },
75
+ { name: 'zhihu', script: 'autoresearch/eval-zhihu.ts' },
76
+ ].filter(s => !singleSuite || s.name === singleSuite);
77
+
78
+ console.log(`\n🔬 Combined AutoResearch — ${suites.length} suites\n`);
79
+
80
+ const results: SuiteResult[] = [];
81
+ for (const suite of suites) {
82
+ console.log(` Running ${suite.name}...`);
83
+ const result = runSuite(suite.name, suite.script);
84
+ results.push(result);
85
+ const icon = result.passed === result.total ? '✓' : '✗';
86
+ console.log(` ${icon} ${result.name}: ${result.passed}/${result.total} (${Math.round(result.duration / 1000)}s)`);
87
+ if (result.failures.length > 0) {
88
+ for (const f of result.failures.slice(0, 5)) {
89
+ console.log(` ✗ ${f}`);
90
+ }
91
+ }
92
+ }
93
+
94
+ // Summary
95
+ const totalPassed = results.reduce((s, r) => s + r.passed, 0);
96
+ const totalTasks = results.reduce((s, r) => s + r.total, 0);
97
+ const totalDuration = results.reduce((s, r) => s + r.duration, 0);
98
+ const allFailures = results.flatMap(r => r.failures.map(f => `${r.name}:${f}`));
99
+
100
+ console.log(`\n${'━'.repeat(50)}`);
101
+ console.log(` Combined: ${totalPassed}/${totalTasks}`);
102
+ for (const r of results) {
103
+ console.log(` ${r.name}: ${r.passed}/${r.total}`);
104
+ }
105
+ console.log(` Time: ${Math.round(totalDuration / 60000)}min`);
106
+ if (allFailures.length > 0) {
107
+ console.log(`\n All failures:`);
108
+ for (const f of allFailures) console.log(` ✗ ${f}`);
109
+ }
110
+
111
+ // Save result
112
+ mkdirSync(RESULTS_DIR, { recursive: true });
113
+ const existing = readdirSync(RESULTS_DIR).filter(f => f.startsWith('all-')).length;
114
+ const roundNum = String(existing + 1).padStart(3, '0');
115
+ const resultPath = join(RESULTS_DIR, `all-${roundNum}.json`);
116
+ writeFileSync(resultPath, JSON.stringify({
117
+ timestamp: new Date().toISOString(),
118
+ score: `${totalPassed}/${totalTasks}`,
119
+ suites: Object.fromEntries(results.map(r => [r.name, `${r.passed}/${r.total}`])),
120
+ failures: allFailures,
121
+ duration: `${Math.round(totalDuration / 60000)}min`,
122
+ }, null, 2), 'utf-8');
123
+ console.log(`\n Results saved to: ${resultPath}`);
124
+ console.log(`\nSCORE=${totalPassed}/${totalTasks}`);
125
+ }
126
+
127
+ main();
@@ -76,7 +76,7 @@ function runCommand(cmd: string): string {
76
76
  stdio: ['pipe', 'pipe', 'pipe'],
77
77
  }).trim();
78
78
  } catch (err: any) {
79
- return err.stdout?.trim() ?? '';
79
+ return err.stdout?.trim() || err.stderr?.trim() || '';
80
80
  }
81
81
  }
82
82