runwork 0.15.0 → 0.15.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 (403) hide show
  1. package/dist/index.js +19272 -116
  2. package/package.json +4 -4
  3. package/dist/__tests__/curl-parser.test.d.ts +0 -1
  4. package/dist/__tests__/curl-parser.test.js +0 -250
  5. package/dist/__tests__/install-scripts.test.d.ts +0 -1
  6. package/dist/__tests__/install-scripts.test.js +0 -280
  7. package/dist/__tests__/types-manager.test.d.ts +0 -1
  8. package/dist/__tests__/types-manager.test.js +0 -89
  9. package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
  10. package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
  11. package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
  12. package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -97
  13. package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
  14. package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
  15. package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
  16. package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
  17. package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
  18. package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
  19. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
  20. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
  21. package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
  22. package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
  23. package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
  24. package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
  25. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
  26. package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
  27. package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
  28. package/dist/agents/__tests__/codex-instructions.test.js +0 -57
  29. package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
  30. package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
  31. package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
  32. package/dist/agents/__tests__/codex-stats.test.js +0 -370
  33. package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
  34. package/dist/agents/__tests__/cursor-merge.test.js +0 -66
  35. package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
  36. package/dist/agents/__tests__/cursor-stats.test.js +0 -183
  37. package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
  38. package/dist/agents/__tests__/defaults-merge.test.js +0 -268
  39. package/dist/agents/__tests__/detection.test.d.ts +0 -1
  40. package/dist/agents/__tests__/detection.test.js +0 -89
  41. package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
  42. package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
  43. package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
  44. package/dist/agents/__tests__/instruction-hint.test.js +0 -69
  45. package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
  46. package/dist/agents/__tests__/intro-skill.test.js +0 -193
  47. package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
  48. package/dist/agents/__tests__/schema-validation.test.js +0 -212
  49. package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
  50. package/dist/agents/__tests__/skill-slug.test.js +0 -77
  51. package/dist/agents/claude-code.d.ts +0 -53
  52. package/dist/agents/claude-code.js +0 -754
  53. package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
  54. package/dist/agents/claude-desktop-plugin-tree.js +0 -143
  55. package/dist/agents/claude-desktop.d.ts +0 -47
  56. package/dist/agents/claude-desktop.js +0 -684
  57. package/dist/agents/cline.d.ts +0 -15
  58. package/dist/agents/cline.js +0 -130
  59. package/dist/agents/codex.d.ts +0 -44
  60. package/dist/agents/codex.js +0 -453
  61. package/dist/agents/conversation-skills.d.ts +0 -18
  62. package/dist/agents/conversation-skills.js +0 -229
  63. package/dist/agents/cursor.d.ts +0 -48
  64. package/dist/agents/cursor.js +0 -324
  65. package/dist/agents/default-config.d.ts +0 -30
  66. package/dist/agents/default-config.js +0 -67
  67. package/dist/agents/defaults-merge.d.ts +0 -72
  68. package/dist/agents/defaults-merge.js +0 -131
  69. package/dist/agents/detect.d.ts +0 -4
  70. package/dist/agents/detect.js +0 -67
  71. package/dist/agents/detection.d.ts +0 -18
  72. package/dist/agents/detection.js +0 -94
  73. package/dist/agents/gemini.d.ts +0 -15
  74. package/dist/agents/gemini.js +0 -122
  75. package/dist/agents/generic-adapter.d.ts +0 -25
  76. package/dist/agents/generic-adapter.js +0 -151
  77. package/dist/agents/intro-skill.d.ts +0 -45
  78. package/dist/agents/intro-skill.js +0 -447
  79. package/dist/agents/registry-data.d.ts +0 -192
  80. package/dist/agents/registry-data.js +0 -669
  81. package/dist/agents/registry.d.ts +0 -13
  82. package/dist/agents/registry.js +0 -36
  83. package/dist/agents/runtime-detection.d.ts +0 -82
  84. package/dist/agents/runtime-detection.js +0 -271
  85. package/dist/agents/session-start-hook.d.ts +0 -37
  86. package/dist/agents/session-start-hook.js +0 -159
  87. package/dist/agents/types.d.ts +0 -171
  88. package/dist/agents/types.js +0 -75
  89. package/dist/agents/utils/instruction-hint.d.ts +0 -21
  90. package/dist/agents/utils/instruction-hint.js +0 -108
  91. package/dist/agents/utils/json-config.d.ts +0 -19
  92. package/dist/agents/utils/json-config.js +0 -69
  93. package/dist/agents/utils/toml-config.d.ts +0 -8
  94. package/dist/agents/utils/toml-config.js +0 -27
  95. package/dist/agents/windsurf.d.ts +0 -14
  96. package/dist/agents/windsurf.js +0 -102
  97. package/dist/api/__tests__/client.test.d.ts +0 -1
  98. package/dist/api/__tests__/client.test.js +0 -272
  99. package/dist/api/client.d.ts +0 -326
  100. package/dist/api/client.js +0 -427
  101. package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
  102. package/dist/auth/__tests__/login-flow.test.js +0 -101
  103. package/dist/auth/__tests__/store.test.d.ts +0 -1
  104. package/dist/auth/__tests__/store.test.js +0 -132
  105. package/dist/auth/login-flow.d.ts +0 -26
  106. package/dist/auth/login-flow.js +0 -137
  107. package/dist/auth/store.d.ts +0 -5
  108. package/dist/auth/store.js +0 -62
  109. package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
  110. package/dist/commands/__tests__/clone-args.test.js +0 -51
  111. package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
  112. package/dist/commands/__tests__/clone-source-result.test.js +0 -45
  113. package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
  114. package/dist/commands/__tests__/info-merge.test.js +0 -55
  115. package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
  116. package/dist/commands/__tests__/mcp-entries.test.js +0 -48
  117. package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
  118. package/dist/commands/__tests__/setup-persona.test.js +0 -31
  119. package/dist/commands/__tests__/setup.test.d.ts +0 -1
  120. package/dist/commands/__tests__/setup.test.js +0 -81
  121. package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
  122. package/dist/commands/__tests__/sync-redetect.test.js +0 -96
  123. package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
  124. package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
  125. package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
  126. package/dist/commands/__tests__/upgrade.test.js +0 -157
  127. package/dist/commands/agents.d.ts +0 -2
  128. package/dist/commands/agents.js +0 -160
  129. package/dist/commands/api-keys.d.ts +0 -2
  130. package/dist/commands/api-keys.js +0 -95
  131. package/dist/commands/apps.d.ts +0 -2
  132. package/dist/commands/apps.js +0 -82
  133. package/dist/commands/build-plugin.d.ts +0 -2
  134. package/dist/commands/build-plugin.js +0 -135
  135. package/dist/commands/clone.d.ts +0 -60
  136. package/dist/commands/clone.js +0 -271
  137. package/dist/commands/components.d.ts +0 -2
  138. package/dist/commands/components.js +0 -43
  139. package/dist/commands/deploy.d.ts +0 -2
  140. package/dist/commands/deploy.js +0 -279
  141. package/dist/commands/dev.d.ts +0 -11
  142. package/dist/commands/dev.js +0 -1011
  143. package/dist/commands/doctor.d.ts +0 -2
  144. package/dist/commands/doctor.js +0 -230
  145. package/dist/commands/endpoints.d.ts +0 -2
  146. package/dist/commands/endpoints.js +0 -189
  147. package/dist/commands/entities.d.ts +0 -2
  148. package/dist/commands/entities.js +0 -198
  149. package/dist/commands/files.d.ts +0 -2
  150. package/dist/commands/files.js +0 -193
  151. package/dist/commands/inbox.d.ts +0 -11
  152. package/dist/commands/inbox.js +0 -60
  153. package/dist/commands/info.d.ts +0 -178
  154. package/dist/commands/info.js +0 -455
  155. package/dist/commands/init.d.ts +0 -21
  156. package/dist/commands/init.js +0 -185
  157. package/dist/commands/integrations.d.ts +0 -2
  158. package/dist/commands/integrations.js +0 -233
  159. package/dist/commands/login.d.ts +0 -2
  160. package/dist/commands/login.js +0 -44
  161. package/dist/commands/logout.d.ts +0 -2
  162. package/dist/commands/logout.js +0 -13
  163. package/dist/commands/logs.d.ts +0 -2
  164. package/dist/commands/logs.js +0 -232
  165. package/dist/commands/mcp-entries.d.ts +0 -13
  166. package/dist/commands/mcp-entries.js +0 -26
  167. package/dist/commands/mcp.d.ts +0 -2
  168. package/dist/commands/mcp.js +0 -245
  169. package/dist/commands/open.d.ts +0 -2
  170. package/dist/commands/open.js +0 -53
  171. package/dist/commands/resume.d.ts +0 -2
  172. package/dist/commands/resume.js +0 -289
  173. package/dist/commands/save-convo.d.ts +0 -8
  174. package/dist/commands/save-convo.js +0 -20
  175. package/dist/commands/schedules.d.ts +0 -2
  176. package/dist/commands/schedules.js +0 -221
  177. package/dist/commands/setup.d.ts +0 -27
  178. package/dist/commands/setup.js +0 -177
  179. package/dist/commands/share-convo.d.ts +0 -24
  180. package/dist/commands/share-convo.js +0 -167
  181. package/dist/commands/skills.d.ts +0 -2
  182. package/dist/commands/skills.js +0 -352
  183. package/dist/commands/sync-telemetry.d.ts +0 -33
  184. package/dist/commands/sync-telemetry.js +0 -186
  185. package/dist/commands/sync.d.ts +0 -37
  186. package/dist/commands/sync.js +0 -702
  187. package/dist/commands/uninstall.d.ts +0 -2
  188. package/dist/commands/uninstall.js +0 -145
  189. package/dist/commands/upgrade.d.ts +0 -14
  190. package/dist/commands/upgrade.js +0 -217
  191. package/dist/commands/validate.d.ts +0 -2
  192. package/dist/commands/validate.js +0 -89
  193. package/dist/commands/welcome.d.ts +0 -1
  194. package/dist/commands/welcome.js +0 -86
  195. package/dist/commands/workflows.d.ts +0 -2
  196. package/dist/commands/workflows.js +0 -187
  197. package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
  198. package/dist/deploy/__tests__/deploy-state.test.js +0 -80
  199. package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
  200. package/dist/deploy/__tests__/deploy-status.test.js +0 -41
  201. package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
  202. package/dist/deploy/__tests__/detach-args.test.js +0 -30
  203. package/dist/deploy/deploy-state.d.ts +0 -36
  204. package/dist/deploy/deploy-state.js +0 -63
  205. package/dist/deploy/deploy-status.d.ts +0 -21
  206. package/dist/deploy/deploy-status.js +0 -36
  207. package/dist/deploy/detach.d.ts +0 -32
  208. package/dist/deploy/detach.js +0 -71
  209. package/dist/dev/__tests__/attach.test.d.ts +0 -1
  210. package/dist/dev/__tests__/attach.test.js +0 -296
  211. package/dist/dev/__tests__/detach.test.d.ts +0 -1
  212. package/dist/dev/__tests__/detach.test.js +0 -404
  213. package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
  214. package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
  215. package/dist/dev/__tests__/session.test.d.ts +0 -1
  216. package/dist/dev/__tests__/session.test.js +0 -446
  217. package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
  218. package/dist/dev/__tests__/startup-sync.test.js +0 -32
  219. package/dist/dev/__tests__/stop.test.d.ts +0 -1
  220. package/dist/dev/__tests__/stop.test.js +0 -172
  221. package/dist/dev/attach.d.ts +0 -120
  222. package/dist/dev/attach.js +0 -269
  223. package/dist/dev/detach.d.ts +0 -187
  224. package/dist/dev/detach.js +0 -292
  225. package/dist/dev/preview-url-poller.d.ts +0 -35
  226. package/dist/dev/preview-url-poller.js +0 -50
  227. package/dist/dev/session.d.ts +0 -175
  228. package/dist/dev/session.js +0 -258
  229. package/dist/dev/startup-sync.d.ts +0 -23
  230. package/dist/dev/startup-sync.js +0 -14
  231. package/dist/dev/stop.d.ts +0 -52
  232. package/dist/dev/stop.js +0 -101
  233. package/dist/devtools/registry-data.d.ts +0 -46
  234. package/dist/devtools/registry-data.js +0 -40
  235. package/dist/generated/bundled-types.d.ts +0 -1
  236. package/dist/generated/bundled-types.js +0 -46
  237. package/dist/generated/version.d.ts +0 -1
  238. package/dist/generated/version.js +0 -2
  239. package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
  240. package/dist/git/__tests__/auto-commit.test.js +0 -431
  241. package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
  242. package/dist/git/__tests__/classify-sync-error.test.js +0 -57
  243. package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
  244. package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
  245. package/dist/git/__tests__/credentials.test.d.ts +0 -1
  246. package/dist/git/__tests__/credentials.test.js +0 -141
  247. package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
  248. package/dist/git/__tests__/deploy-guard.test.js +0 -61
  249. package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
  250. package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
  251. package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
  252. package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
  253. package/dist/git/__tests__/identity.test.d.ts +0 -1
  254. package/dist/git/__tests__/identity.test.js +0 -146
  255. package/dist/git/__tests__/manifest.test.d.ts +0 -1
  256. package/dist/git/__tests__/manifest.test.js +0 -446
  257. package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
  258. package/dist/git/__tests__/preflight-resolution.test.js +0 -366
  259. package/dist/git/__tests__/preflight.test.d.ts +0 -1
  260. package/dist/git/__tests__/preflight.test.js +0 -36
  261. package/dist/git/__tests__/repo-config.test.d.ts +0 -1
  262. package/dist/git/__tests__/repo-config.test.js +0 -26
  263. package/dist/git/__tests__/sync.test.d.ts +0 -1
  264. package/dist/git/__tests__/sync.test.js +0 -405
  265. package/dist/git/auto-commit.d.ts +0 -35
  266. package/dist/git/auto-commit.js +0 -293
  267. package/dist/git/classify-sync-error.d.ts +0 -21
  268. package/dist/git/classify-sync-error.js +0 -111
  269. package/dist/git/credentials.d.ts +0 -75
  270. package/dist/git/credentials.js +0 -164
  271. package/dist/git/critical-files.d.ts +0 -20
  272. package/dist/git/critical-files.js +0 -68
  273. package/dist/git/deploy-guard.d.ts +0 -53
  274. package/dist/git/deploy-guard.js +0 -78
  275. package/dist/git/identity.d.ts +0 -44
  276. package/dist/git/identity.js +0 -133
  277. package/dist/git/preflight.d.ts +0 -57
  278. package/dist/git/preflight.js +0 -276
  279. package/dist/git/remote.d.ts +0 -37
  280. package/dist/git/remote.js +0 -75
  281. package/dist/git/repo-config.d.ts +0 -8
  282. package/dist/git/repo-config.js +0 -29
  283. package/dist/git/sync.d.ts +0 -15
  284. package/dist/git/sync.js +0 -159
  285. package/dist/health/__tests__/checks.test.d.ts +0 -1
  286. package/dist/health/__tests__/checks.test.js +0 -357
  287. package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
  288. package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
  289. package/dist/health/__tests__/fix.test.d.ts +0 -1
  290. package/dist/health/__tests__/fix.test.js +0 -72
  291. package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
  292. package/dist/health/__tests__/runner-filter.test.js +0 -61
  293. package/dist/health/checks.d.ts +0 -42
  294. package/dist/health/checks.js +0 -636
  295. package/dist/health/fix.d.ts +0 -22
  296. package/dist/health/fix.js +0 -62
  297. package/dist/health/runner.d.ts +0 -8
  298. package/dist/health/runner.js +0 -47
  299. package/dist/health/types.d.ts +0 -12
  300. package/dist/health/types.js +0 -1
  301. package/dist/index.d.ts +0 -1
  302. package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
  303. package/dist/logs/__tests__/tailer-format.test.js +0 -43
  304. package/dist/logs/tailer.d.ts +0 -17
  305. package/dist/logs/tailer.js +0 -217
  306. package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
  307. package/dist/sync/__tests__/change-detect.test.js +0 -123
  308. package/dist/sync/__tests__/hash.test.d.ts +0 -1
  309. package/dist/sync/__tests__/hash.test.js +0 -18
  310. package/dist/sync/change-detect.d.ts +0 -19
  311. package/dist/sync/change-detect.js +0 -136
  312. package/dist/sync/conflict-ui.d.ts +0 -5
  313. package/dist/sync/conflict-ui.js +0 -78
  314. package/dist/sync/executor.d.ts +0 -23
  315. package/dist/sync/executor.js +0 -102
  316. package/dist/sync/hash.d.ts +0 -1
  317. package/dist/sync/hash.js +0 -4
  318. package/dist/sync/types.d.ts +0 -24
  319. package/dist/sync/types.js +0 -1
  320. package/dist/template/manifest.d.ts +0 -17
  321. package/dist/template/manifest.js +0 -145
  322. package/dist/tools/types.d.ts +0 -52
  323. package/dist/tools/types.js +0 -8
  324. package/dist/types-manager.d.ts +0 -1
  325. package/dist/types-manager.js +0 -35
  326. package/dist/types.d.ts +0 -349
  327. package/dist/types.js +0 -1
  328. package/dist/ui/__tests__/banner.test.d.ts +0 -1
  329. package/dist/ui/__tests__/banner.test.js +0 -98
  330. package/dist/ui/__tests__/colors.test.d.ts +0 -1
  331. package/dist/ui/__tests__/colors.test.js +0 -22
  332. package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
  333. package/dist/ui/__tests__/keyboard.test.js +0 -34
  334. package/dist/ui/__tests__/status-line.test.d.ts +0 -1
  335. package/dist/ui/__tests__/status-line.test.js +0 -54
  336. package/dist/ui/banner.d.ts +0 -29
  337. package/dist/ui/banner.js +0 -153
  338. package/dist/ui/colors.d.ts +0 -4
  339. package/dist/ui/colors.js +0 -7
  340. package/dist/ui/keyboard.d.ts +0 -12
  341. package/dist/ui/keyboard.js +0 -61
  342. package/dist/ui/status-line.d.ts +0 -6
  343. package/dist/ui/status-line.js +0 -53
  344. package/dist/utils/__tests__/format-error.test.d.ts +0 -1
  345. package/dist/utils/__tests__/format-error.test.js +0 -43
  346. package/dist/utils/__tests__/help-json.test.d.ts +0 -1
  347. package/dist/utils/__tests__/help-json.test.js +0 -39
  348. package/dist/utils/__tests__/http.test.d.ts +0 -1
  349. package/dist/utils/__tests__/http.test.js +0 -381
  350. package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
  351. package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
  352. package/dist/utils/__tests__/output.test.d.ts +0 -1
  353. package/dist/utils/__tests__/output.test.js +0 -38
  354. package/dist/utils/__tests__/prompt.test.d.ts +0 -1
  355. package/dist/utils/__tests__/prompt.test.js +0 -27
  356. package/dist/utils/__tests__/resolve.test.d.ts +0 -1
  357. package/dist/utils/__tests__/resolve.test.js +0 -95
  358. package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
  359. package/dist/utils/__tests__/sqlite.test.js +0 -89
  360. package/dist/utils/agent-guidance.d.ts +0 -47
  361. package/dist/utils/agent-guidance.js +0 -128
  362. package/dist/utils/app-info.d.ts +0 -70
  363. package/dist/utils/app-info.js +0 -167
  364. package/dist/utils/curl-parser.d.ts +0 -12
  365. package/dist/utils/curl-parser.js +0 -162
  366. package/dist/utils/data-input.d.ts +0 -1
  367. package/dist/utils/data-input.js +0 -38
  368. package/dist/utils/format-error.d.ts +0 -10
  369. package/dist/utils/format-error.js +0 -38
  370. package/dist/utils/fs.d.ts +0 -5
  371. package/dist/utils/fs.js +0 -23
  372. package/dist/utils/help-json.d.ts +0 -70
  373. package/dist/utils/help-json.js +0 -88
  374. package/dist/utils/http.d.ts +0 -46
  375. package/dist/utils/http.js +0 -421
  376. package/dist/utils/ignore-matcher.d.ts +0 -47
  377. package/dist/utils/ignore-matcher.js +0 -132
  378. package/dist/utils/output.d.ts +0 -17
  379. package/dist/utils/output.js +0 -27
  380. package/dist/utils/prompt.d.ts +0 -5
  381. package/dist/utils/prompt.js +0 -42
  382. package/dist/utils/resolve.d.ts +0 -12
  383. package/dist/utils/resolve.js +0 -52
  384. package/dist/utils/setup-state.d.ts +0 -3
  385. package/dist/utils/setup-state.js +0 -19
  386. package/dist/utils/sqlite-adapter.d.ts +0 -48
  387. package/dist/utils/sqlite-adapter.js +0 -147
  388. package/dist/utils/sqlite.d.ts +0 -14
  389. package/dist/utils/sqlite.js +0 -14
  390. package/dist/utils/subprocess.d.ts +0 -19
  391. package/dist/utils/subprocess.js +0 -27
  392. package/dist/utils/which.d.ts +0 -14
  393. package/dist/utils/which.js +0 -47
  394. package/dist/utils/zip.d.ts +0 -7
  395. package/dist/utils/zip.js +0 -42
  396. package/dist/validate/__tests__/validate.test.d.ts +0 -1
  397. package/dist/validate/__tests__/validate.test.js +0 -42
  398. package/dist/validate/freshness.d.ts +0 -28
  399. package/dist/validate/freshness.js +0 -48
  400. package/dist/validate/preview.d.ts +0 -21
  401. package/dist/validate/preview.js +0 -39
  402. package/dist/workspace/resolve.d.ts +0 -19
  403. package/dist/workspace/resolve.js +0 -100
@@ -1,754 +0,0 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'fs';
2
- import { join } from 'path';
3
- import { homedir, platform } from 'os';
4
- import { execFileSync } from '../utils/subprocess.js';
5
- import { whichBinary } from '../utils/which.js';
6
- import { buildSkillMd } from './types.js';
7
- import { mergeJsonMcpServers, readJsonConfig, writeJsonConfig, removeRunworkMcpServers } from './utils/json-config.js';
8
- import { writeHintToFile, writeTeamInstructionsToFile, removeHintFromFile, removeTeamInstructionsFromFile } from './utils/instruction-hint.js';
9
- import { SESSION_START_HOOK_SCRIPT } from './session-start-hook.js';
10
- const PLUGIN_NAME = 'runwork';
11
- const PLUGIN_VERSION = '1.0.0';
12
- function getPluginJson() {
13
- return {
14
- name: PLUGIN_NAME,
15
- version: PLUGIN_VERSION,
16
- description: 'Skills and tools from your Runwork workspace',
17
- author: { name: 'Runwork' },
18
- homepage: 'https://www.runwork.ai',
19
- };
20
- }
21
- function getMarketplaceJson() {
22
- return {
23
- name: 'runwork',
24
- owner: { name: 'Runwork' },
25
- plugins: [
26
- {
27
- name: PLUGIN_NAME,
28
- source: `./plugins/${PLUGIN_NAME}`,
29
- description: 'Skills and tools from your Runwork workspace',
30
- },
31
- ],
32
- };
33
- }
34
- export class ClaudeCodeAdapter {
35
- name = 'Claude Code';
36
- slug = 'claude-code';
37
- mcpProvidesSkills = true;
38
- async detect() {
39
- if (whichBinary('claude'))
40
- return true;
41
- // Fallback: check app bundle on macOS
42
- if (platform() === 'darwin')
43
- return existsSync('/Applications/Claude.app');
44
- return false;
45
- }
46
- supportsMcpScope(_scope) {
47
- return true;
48
- }
49
- supportsSkills() {
50
- return true;
51
- }
52
- async writeMcpServers(servers, scope) {
53
- if (scope === 'project') {
54
- // Project scope: write to .mcp.json (standard Claude Code location)
55
- const filePath = join(process.cwd(), '.mcp.json');
56
- const entries = {};
57
- for (const s of servers) {
58
- entries[s.name] = {
59
- type: 'http',
60
- url: s.url,
61
- ...(s.headers ? { headers: s.headers } : {}),
62
- ...(s.description ? { description: s.description } : {}),
63
- };
64
- }
65
- mergeJsonMcpServers(filePath, entries, 'mcpServers');
66
- }
67
- else {
68
- // User scope: write MCP config both in global settings and inside the plugin
69
- const settingsPath = join(homedir(), '.claude', 'settings.json');
70
- const entries = {};
71
- for (const s of servers) {
72
- entries[s.name] = {
73
- type: 'http',
74
- url: s.url,
75
- ...(s.headers ? { headers: s.headers } : {}),
76
- ...(s.description ? { description: s.description } : {}),
77
- };
78
- }
79
- mergeJsonMcpServers(settingsPath, entries, 'mcpServers');
80
- // Also write .mcp.json in the plugin directory
81
- const pluginDir = this.getPluginDir();
82
- mkdirSync(pluginDir, { recursive: true });
83
- const pluginMcpPath = join(pluginDir, '.mcp.json');
84
- const marketDir = this.getMarketplaceDir();
85
- mkdirSync(marketDir, { recursive: true });
86
- const marketplaceMcpPath = join(marketDir, '.mcp.json');
87
- const pluginEntries = {};
88
- for (const s of servers) {
89
- pluginEntries[s.name] = {
90
- type: 'http',
91
- url: s.url,
92
- ...(s.headers ? { headers: s.headers } : {}),
93
- ...(s.description ? { description: s.description } : {}),
94
- };
95
- }
96
- writeJsonConfig(pluginMcpPath, pluginEntries);
97
- writeJsonConfig(marketplaceMcpPath, pluginEntries);
98
- }
99
- }
100
- /**
101
- * Install the Runwork SessionStart hook into the plugin tree (user scope).
102
- * The hook writes ~/.runwork/sessions/<sessionId>.json with the active
103
- * conversation's transcript path + metadata, used by `runwork share-convo`
104
- * for high-fidelity capture and by `runwork resume` for placement.
105
- *
106
- * Called as part of user-scope writeSkills() to keep sync flow consistent.
107
- * Emits a one-line confirmation matching the format other adapter steps
108
- * use (` [Claude Code] Installed ... (user)`) so `runwork sync` output
109
- * shows whether the hook actually landed.
110
- */
111
- installSessionStartHook(pluginDir, label) {
112
- const hooksDir = join(pluginDir, 'hooks');
113
- mkdirSync(hooksDir, { recursive: true });
114
- const scriptPath = join(hooksDir, 'on-session-start.sh');
115
- writeFileSync(scriptPath, SESSION_START_HOOK_SCRIPT);
116
- try {
117
- // Best-effort executable bit; chmod is a no-op on Windows.
118
- chmodSync(scriptPath, 0o755);
119
- }
120
- catch {
121
- /* not fatal */
122
- }
123
- const hooksManifest = {
124
- SessionStart: [
125
- { command: '${CLAUDE_PLUGIN_ROOT}/hooks/on-session-start.sh' },
126
- ],
127
- };
128
- writeFileSync(join(hooksDir, 'hooks.json'), JSON.stringify(hooksManifest, null, 2));
129
- console.log(` [Claude Code] Installed SessionStart hook (${label}) -> ${scriptPath}`);
130
- }
131
- async writeSkills(skills, scope) {
132
- // Always write to the standard skills directory (guaranteed to work)
133
- const baseDir = scope === 'project'
134
- ? join(process.cwd(), '.claude', 'skills')
135
- : join(homedir(), '.claude', 'skills');
136
- for (const skill of skills) {
137
- const skillDir = join(baseDir, skill.filename);
138
- cleanupOldSkillDir(baseDir, skill);
139
- mkdirSync(skillDir, { recursive: true });
140
- writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
141
- }
142
- // User scope: also write as a plugin for native plugin UI support
143
- if (scope === 'user') {
144
- const pluginDir = this.getPluginDir();
145
- // Create plugin.json
146
- const pluginJsonDir = join(pluginDir, '.claude-plugin');
147
- mkdirSync(pluginJsonDir, { recursive: true });
148
- writeFileSync(join(pluginJsonDir, 'plugin.json'), JSON.stringify(getPluginJson(), null, 2));
149
- // Write skill files inside the plugin
150
- for (const skill of skills) {
151
- const skillDir = join(pluginDir, 'skills', skill.filename);
152
- cleanupOldSkillDir(join(pluginDir, 'skills'), skill);
153
- mkdirSync(skillDir, { recursive: true });
154
- writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
155
- }
156
- // Also write to the marketplace directory
157
- const marketDir = this.getMarketplaceDir();
158
- const marketPluginJsonDir = join(marketDir, '.claude-plugin');
159
- mkdirSync(marketPluginJsonDir, { recursive: true });
160
- writeFileSync(join(marketPluginJsonDir, 'plugin.json'), JSON.stringify(getPluginJson(), null, 2));
161
- for (const skill of skills) {
162
- const skillDir = join(marketDir, 'skills', skill.filename);
163
- cleanupOldSkillDir(join(marketDir, 'skills'), skill);
164
- mkdirSync(skillDir, { recursive: true });
165
- writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
166
- }
167
- // Register in installed_plugins.json
168
- this.registerPlugin(pluginDir);
169
- }
170
- }
171
- /**
172
- * Install the runwork SessionStart hook for Claude Code (user scope only).
173
- * Called once per sync by the main sync loop AFTER writeSkills has
174
- * populated the plugin directories. Kept separate from writeSkills because
175
- * writeSkills is also invoked per-skill by the diff executor during
176
- * push/pull, and the hook install + log line must not repeat for every
177
- * skill change.
178
- */
179
- async writeBuiltInHooks(scope) {
180
- if (scope !== 'user')
181
- return;
182
- const pluginDir = this.getPluginDir();
183
- const marketDir = this.getMarketplaceDir();
184
- if (existsSync(pluginDir)) {
185
- this.installSessionStartHook(pluginDir, 'plugin cache');
186
- }
187
- if (existsSync(marketDir)) {
188
- this.installSessionStartHook(marketDir, 'marketplace');
189
- }
190
- }
191
- async writeInstructionHint(hint, scope) {
192
- const filePath = scope === 'project'
193
- ? join(process.cwd(), '.claude', 'CLAUDE.md')
194
- : join(homedir(), '.claude', 'CLAUDE.md');
195
- writeHintToFile(filePath, hint);
196
- }
197
- async writeTeamInstructions(instructions, scope) {
198
- // Write to CLAUDE.md via markers (direct instruction file approach)
199
- const filePath = scope === 'project'
200
- ? join(process.cwd(), '.claude', 'CLAUDE.md')
201
- : join(homedir(), '.claude', 'CLAUDE.md');
202
- writeTeamInstructionsToFile(filePath, instructions);
203
- // Also write as a plugin skill (same mechanism as Claude Desktop)
204
- if (scope === 'user') {
205
- const skillContent = `---\nname: runwork-team-instructions\ndescription: Team instructions from your Runwork workspace. Always follow these guidelines.\n---\n\n${instructions}`;
206
- const pluginDir = this.getPluginDir();
207
- const marketDir = this.getMarketplaceDir();
208
- for (const dir of [
209
- join(pluginDir, 'skills', 'runwork-team-instructions'),
210
- join(marketDir, 'skills', 'runwork-team-instructions'),
211
- ]) {
212
- mkdirSync(dir, { recursive: true });
213
- writeFileSync(join(dir, 'SKILL.md'), skillContent);
214
- }
215
- }
216
- }
217
- // ── Agent config (model, permissions) ──────────────────────────────
218
- async writeAgentConfig(config, scope) {
219
- const settingsPath = scope === 'project'
220
- ? join(process.cwd(), '.claude', 'settings.json')
221
- : join(homedir(), '.claude', 'settings.json');
222
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
223
- let settings = {};
224
- if (existsSync(settingsPath)) {
225
- try {
226
- settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
227
- }
228
- catch { /* start fresh */ }
229
- }
230
- if (config.modelPreference) {
231
- settings.model = config.modelPreference;
232
- }
233
- if (config.permissionRules) {
234
- if (!settings.permissions)
235
- settings.permissions = {};
236
- const perms = settings.permissions;
237
- const MANAGED_MARKER = '# runwork-managed';
238
- if (config.permissionRules.allow) {
239
- const cleanExisting = this.removeAfterMarker(perms.allow ?? [], MANAGED_MARKER);
240
- perms.allow = [...cleanExisting, MANAGED_MARKER, ...config.permissionRules.allow];
241
- }
242
- if (config.permissionRules.deny) {
243
- const cleanExisting = this.removeAfterMarker(perms.deny ?? [], MANAGED_MARKER);
244
- perms.deny = [...cleanExisting, MANAGED_MARKER, ...config.permissionRules.deny];
245
- }
246
- if (config.permissionRules.defaultMode) {
247
- perms.defaultMode = config.permissionRules.defaultMode;
248
- }
249
- }
250
- mkdirSync(join(settingsPath, '..'), { recursive: true });
251
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
252
- }
253
- /** Remove the managed marker and all entries after it from a permissions array */
254
- removeAfterMarker(arr, marker) {
255
- const idx = arr.indexOf(marker);
256
- return idx >= 0 ? arr.slice(0, idx) : [...arr];
257
- }
258
- /** Return entries after the managed marker for both allow and deny lists. */
259
- async readManagedBlock(scope) {
260
- const settingsPath = scope === 'project'
261
- ? join(process.cwd(), '.claude', 'settings.json')
262
- : join(homedir(), '.claude', 'settings.json');
263
- if (!existsSync(settingsPath))
264
- return undefined;
265
- const MANAGED_MARKER = '# runwork-managed';
266
- try {
267
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
268
- const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
269
- const perms = settings?.permissions;
270
- if (!perms || typeof perms !== 'object')
271
- return { allow: [], deny: [] };
272
- const extractAfter = (arr) => {
273
- if (!Array.isArray(arr))
274
- return [];
275
- const idx = arr.indexOf(MANAGED_MARKER);
276
- return idx >= 0 ? arr.slice(idx + 1).filter((x) => typeof x === 'string') : [];
277
- };
278
- return {
279
- allow: extractAfter(perms.allow),
280
- deny: extractAfter(perms.deny),
281
- };
282
- }
283
- catch {
284
- return undefined;
285
- }
286
- }
287
- // ── Cleanup (uninstall) ────────────────────────────────────────────
288
- async cleanup(scope, manifest) {
289
- // 1. Remove MCP server entries
290
- if (scope === 'project') {
291
- removeRunworkMcpServers(join(process.cwd(), '.mcp.json'), 'mcpServers');
292
- }
293
- else {
294
- removeRunworkMcpServers(join(homedir(), '.claude', 'settings.json'), 'mcpServers');
295
- }
296
- // 2. Remove only skill directories that we synced (listed in manifest)
297
- const skillsDir = scope === 'project'
298
- ? join(process.cwd(), '.claude', 'skills')
299
- : join(homedir(), '.claude', 'skills');
300
- if (existsSync(skillsDir) && manifest?.skillFilenames.length) {
301
- const allowed = new Set(manifest.skillFilenames);
302
- for (const entry of readdirSync(skillsDir)) {
303
- if (!allowed.has(entry))
304
- continue;
305
- try {
306
- rmSync(join(skillsDir, entry), { recursive: true, force: true });
307
- }
308
- catch { /* best-effort */ }
309
- }
310
- }
311
- // 3. Remove instruction hints and team instructions
312
- const instructionFile = scope === 'project'
313
- ? join(process.cwd(), '.claude', 'CLAUDE.md')
314
- : join(homedir(), '.claude', 'CLAUDE.md');
315
- removeHintFromFile(instructionFile);
316
- removeTeamInstructionsFromFile(instructionFile);
317
- // 4. Remove agent config overrides (managed permission entries, model, enabledPlugins)
318
- if (scope === 'user') {
319
- const settingsPath = join(homedir(), '.claude', 'settings.json');
320
- if (existsSync(settingsPath)) {
321
- try {
322
- const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
323
- // Remove managed permission entries
324
- if (settings.permissions) {
325
- const MANAGED_MARKER = '# runwork-managed';
326
- if (settings.permissions.allow) {
327
- const idx = settings.permissions.allow.indexOf(MANAGED_MARKER);
328
- if (idx >= 0)
329
- settings.permissions.allow = settings.permissions.allow.slice(0, idx);
330
- }
331
- if (settings.permissions.deny) {
332
- const idx = settings.permissions.deny.indexOf(MANAGED_MARKER);
333
- if (idx >= 0)
334
- settings.permissions.deny = settings.permissions.deny.slice(0, idx);
335
- }
336
- }
337
- // Remove plugin enablement
338
- if (settings.enabledPlugins) {
339
- delete settings.enabledPlugins[`${PLUGIN_NAME}@runwork`];
340
- }
341
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
342
- }
343
- catch { /* best-effort */ }
344
- }
345
- // 5. Remove plugin directories
346
- const pluginDir = this.getPluginDir();
347
- const marketRoot = this.getMarketplaceRoot();
348
- for (const dir of [pluginDir, marketRoot]) {
349
- if (existsSync(dir)) {
350
- try {
351
- rmSync(dir, { recursive: true, force: true });
352
- }
353
- catch { /* best-effort */ }
354
- }
355
- }
356
- // 6. Remove from installed_plugins.json
357
- const pluginsBase = this.getPluginsBaseDir();
358
- const installedPath = join(pluginsBase, 'installed_plugins.json');
359
- if (existsSync(installedPath)) {
360
- try {
361
- const installed = readJsonConfig(installedPath);
362
- if (installed.plugins) {
363
- delete installed.plugins[`${PLUGIN_NAME}@runwork`];
364
- writeJsonConfig(installedPath, installed);
365
- }
366
- }
367
- catch { /* best-effort */ }
368
- }
369
- // 7. Remove from known_marketplaces.json
370
- const marketplacesPath = join(pluginsBase, 'known_marketplaces.json');
371
- if (existsSync(marketplacesPath)) {
372
- try {
373
- const marketplaces = readJsonConfig(marketplacesPath);
374
- delete marketplaces['runwork'];
375
- writeJsonConfig(marketplacesPath, marketplaces);
376
- }
377
- catch { /* best-effort */ }
378
- }
379
- }
380
- }
381
- // ── Usage stats (passive, best-effort) ─────────────────────────────
382
- async readUsageStats(lastSyncAt) {
383
- // Source of truth: ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
384
- // Each line is one user/assistant/system entry. The file grows continuously
385
- // during a live session, so mtime + per-entry timestamp give an accurate
386
- // post-sync activity picture. (stats-cache.json was abandoned upstream and
387
- // session-env/ only records session-start hooks.)
388
- try {
389
- const claudeDir = join(homedir(), '.claude');
390
- if (!existsSync(claudeDir))
391
- return null;
392
- const projectsDir = join(claudeDir, 'projects');
393
- if (!existsSync(projectsDir))
394
- return null;
395
- const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
396
- let sessionCount = 0;
397
- let messageCount = 0;
398
- let toolCallCount = 0;
399
- let inputTokens = 0;
400
- let outputTokens = 0;
401
- let cacheReadTokens = 0;
402
- let latestActivityMs = 0;
403
- // Dedup: ccusage uses ${message.id}:${requestId} to drop retransmissions.
404
- // Entries without both fields pass through undeduped (same behavior).
405
- const seenEntries = new Set();
406
- let cwdEntries;
407
- try {
408
- cwdEntries = readdirSync(projectsDir);
409
- }
410
- catch {
411
- return null;
412
- }
413
- for (const cwd of cwdEntries) {
414
- const cwdPath = join(projectsDir, cwd);
415
- let files;
416
- try {
417
- files = readdirSync(cwdPath);
418
- }
419
- catch {
420
- continue;
421
- }
422
- for (const file of files) {
423
- if (!file.endsWith('.jsonl'))
424
- continue;
425
- const filePath = join(cwdPath, file);
426
- let stat;
427
- try {
428
- stat = statSync(filePath);
429
- }
430
- catch {
431
- continue;
432
- }
433
- if (stat.mtimeMs <= sinceMs)
434
- continue;
435
- let content;
436
- try {
437
- content = readFileSync(filePath, 'utf-8');
438
- }
439
- catch {
440
- continue;
441
- }
442
- let sessionHadActivity = false;
443
- for (const line of content.split('\n')) {
444
- if (!line)
445
- continue;
446
- let entry;
447
- try {
448
- entry = JSON.parse(line);
449
- }
450
- catch {
451
- continue;
452
- }
453
- const tsRaw = entry.timestamp;
454
- if (typeof tsRaw !== 'string')
455
- continue;
456
- const ts = Date.parse(tsRaw);
457
- if (!Number.isFinite(ts) || ts <= sinceMs)
458
- continue;
459
- sessionHadActivity = true;
460
- if (ts > latestActivityMs)
461
- latestActivityMs = ts;
462
- const type = entry.type;
463
- if (type === 'user' || type === 'assistant') {
464
- // Dedup by message.id + requestId (same approach as ccusage)
465
- const msg = entry.message;
466
- const msgId = msg && typeof msg === 'object' ? msg.id : undefined;
467
- const reqId = entry.requestId;
468
- if (typeof msgId === 'string' && typeof reqId === 'string') {
469
- const dedupKey = `${msgId}:${reqId}`;
470
- if (seenEntries.has(dedupKey))
471
- continue;
472
- seenEntries.add(dedupKey);
473
- }
474
- messageCount++;
475
- }
476
- if (type === 'assistant') {
477
- const msg = entry.message;
478
- if (msg && typeof msg === 'object') {
479
- const msgRecord = msg;
480
- const blocks = Array.isArray(msgRecord.content) ? msgRecord.content : [];
481
- for (const block of blocks) {
482
- if (block && typeof block === 'object'
483
- && block.type === 'tool_use') {
484
- toolCallCount++;
485
- }
486
- }
487
- const usage = msgRecord.usage;
488
- if (usage && typeof usage === 'object') {
489
- const u = usage;
490
- if (typeof u.input_tokens === 'number')
491
- inputTokens += u.input_tokens;
492
- if (typeof u.output_tokens === 'number')
493
- outputTokens += u.output_tokens;
494
- if (typeof u.cache_read_input_tokens === 'number') {
495
- cacheReadTokens += u.cache_read_input_tokens;
496
- }
497
- }
498
- }
499
- }
500
- }
501
- if (sessionHadActivity)
502
- sessionCount++;
503
- }
504
- }
505
- if (sessionCount === 0)
506
- return null;
507
- return {
508
- hasNewActivity: true,
509
- sessionCount,
510
- messageCount,
511
- toolCallCount,
512
- tokensUsed: inputTokens + outputTokens,
513
- aiLinesAdded: 0,
514
- aiLinesRemoved: 0,
515
- lastActiveAt: latestActivityMs > 0 ? new Date(latestActivityMs).toISOString() : null,
516
- extra: { inputTokens, outputTokens, cacheReadTokens },
517
- };
518
- }
519
- catch {
520
- return null;
521
- }
522
- }
523
- async readSkillUsage(lastSyncAt) {
524
- // Walk the same JSONL files as readUsageStats and detect actual skill
525
- // invocations. Two verified paths exist in the data:
526
- //
527
- // Path A (model-initiated): assistant message contains a tool_use block
528
- // with name === "Skill" and input.skill === "<skill-name>".
529
- //
530
- // Path B (user-initiated slash command): user message contains
531
- // <command-name>/xxx</command-name>, and the NEXT user message starts
532
- // with "Base directory for this skill:" (confirming the harness treated
533
- // it as a skill, not a built-in command).
534
- //
535
- // MCP skill tools (mcp__*__skill_*) are listed in deferred-tool blocks
536
- // but are never actually invoked in any observed JSONL data.
537
- try {
538
- const projectsDir = join(homedir(), '.claude', 'projects');
539
- if (!existsSync(projectsDir))
540
- return null;
541
- const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
542
- const skillCounts = new Map();
543
- const recordSkill = (name, ts) => {
544
- const existing = skillCounts.get(name);
545
- if (existing) {
546
- existing.count++;
547
- if (ts > existing.lastTs)
548
- existing.lastTs = ts;
549
- }
550
- else {
551
- skillCounts.set(name, { count: 1, lastTs: ts });
552
- }
553
- };
554
- let cwdEntries;
555
- try {
556
- cwdEntries = readdirSync(projectsDir);
557
- }
558
- catch {
559
- return null;
560
- }
561
- for (const cwd of cwdEntries) {
562
- const cwdPath = join(projectsDir, cwd);
563
- let files;
564
- try {
565
- files = readdirSync(cwdPath);
566
- }
567
- catch {
568
- continue;
569
- }
570
- for (const file of files) {
571
- if (!file.endsWith('.jsonl'))
572
- continue;
573
- const filePath = join(cwdPath, file);
574
- let fileStat;
575
- try {
576
- fileStat = statSync(filePath);
577
- }
578
- catch {
579
- continue;
580
- }
581
- if (fileStat.mtimeMs <= sinceMs)
582
- continue;
583
- let content;
584
- try {
585
- content = readFileSync(filePath, 'utf-8');
586
- }
587
- catch {
588
- continue;
589
- }
590
- // Track pending slash command for Path B lookahead
591
- let pendingCommand = null;
592
- for (const line of content.split('\n')) {
593
- if (!line)
594
- continue;
595
- let entry;
596
- try {
597
- entry = JSON.parse(line);
598
- }
599
- catch {
600
- continue;
601
- }
602
- const tsRaw = entry.timestamp;
603
- if (typeof tsRaw !== 'string')
604
- continue;
605
- const ts = Date.parse(tsRaw);
606
- if (!Number.isFinite(ts) || ts <= sinceMs)
607
- continue;
608
- const type = entry.type;
609
- // Path A: Skill tool calls in assistant messages
610
- if (type === 'assistant') {
611
- const msg = entry.message;
612
- if (msg && typeof msg === 'object') {
613
- const blocks = Array.isArray(msg.content)
614
- ? msg.content
615
- : [];
616
- for (const block of blocks) {
617
- if (block && block.type === 'tool_use' && block.name === 'Skill') {
618
- const input = block.input;
619
- if (input && typeof input.skill === 'string') {
620
- recordSkill(input.skill, ts);
621
- }
622
- }
623
- }
624
- }
625
- }
626
- // Path B: slash command -> skill content injection
627
- if (type === 'user') {
628
- const msg = entry.message;
629
- const msgContent = msg?.content;
630
- const text = typeof msgContent === 'string' ? msgContent : '';
631
- // Check if this is a skill content injection following a slash command
632
- if (pendingCommand && text.startsWith('Base directory for this skill:')) {
633
- recordSkill(pendingCommand.name, pendingCommand.ts);
634
- pendingCommand = null;
635
- continue;
636
- }
637
- // Reset pending on any user message that isn't skill content
638
- if (pendingCommand && type === 'user') {
639
- pendingCommand = null;
640
- }
641
- // Check for slash command pattern
642
- const match = text.match(/<command-name>\/?([^<]+)<\/command-name>/);
643
- if (match) {
644
- const cmdName = match[1].replace(/^\//, '');
645
- pendingCommand = { name: cmdName, ts };
646
- }
647
- }
648
- }
649
- }
650
- }
651
- if (skillCounts.size === 0)
652
- return null;
653
- const results = [];
654
- for (const [skillName, { count, lastTs }] of skillCounts) {
655
- results.push({
656
- skillName,
657
- count,
658
- lastUsedAt: new Date(lastTs).toISOString(),
659
- });
660
- }
661
- return results;
662
- }
663
- catch {
664
- return null;
665
- }
666
- }
667
- async readVersion() {
668
- try {
669
- const output = execFileSync('claude', ['--version'], { stdio: 'pipe' }).toString().trim();
670
- return output;
671
- }
672
- catch {
673
- return null;
674
- }
675
- }
676
- // ── Plugin helpers ─────────────────────────────────────────────────
677
- getPluginsBaseDir() {
678
- return join(homedir(), '.claude', 'plugins');
679
- }
680
- getPluginDir() {
681
- return join(this.getPluginsBaseDir(), 'cache', 'runwork', PLUGIN_NAME, PLUGIN_VERSION);
682
- }
683
- /** The marketplace root (contains marketplace.json and plugins/) */
684
- getMarketplaceRoot() {
685
- return join(this.getPluginsBaseDir(), 'marketplaces', 'runwork');
686
- }
687
- /** The plugin directory within the marketplace */
688
- getMarketplaceDir() {
689
- return join(this.getMarketplaceRoot(), 'plugins', PLUGIN_NAME);
690
- }
691
- registerPlugin(pluginDir) {
692
- const pluginsBase = this.getPluginsBaseDir();
693
- mkdirSync(pluginsBase, { recursive: true });
694
- // Register in installed_plugins.json
695
- const installedPath = join(pluginsBase, 'installed_plugins.json');
696
- const installed = readJsonConfig(installedPath);
697
- if (!installed.version)
698
- installed.version = 2;
699
- if (!installed.plugins)
700
- installed.plugins = {};
701
- const pluginKey = `${PLUGIN_NAME}@runwork`;
702
- const wasRegistered = !!installed.plugins[pluginKey];
703
- installed.plugins[pluginKey] = [{
704
- scope: 'user',
705
- installPath: pluginDir,
706
- version: PLUGIN_VERSION,
707
- installedAt: new Date().toISOString(),
708
- lastUpdated: new Date().toISOString(),
709
- }];
710
- writeJsonConfig(installedPath, installed);
711
- // Write marketplace.json catalog
712
- const marketRoot = this.getMarketplaceRoot();
713
- const marketCatalogDir = join(marketRoot, '.claude-plugin');
714
- mkdirSync(marketCatalogDir, { recursive: true });
715
- writeFileSync(join(marketCatalogDir, 'marketplace.json'), JSON.stringify(getMarketplaceJson(), null, 2));
716
- // Register in known_marketplaces.json
717
- const marketplacesPath = join(pluginsBase, 'known_marketplaces.json');
718
- const marketplaces = readJsonConfig(marketplacesPath);
719
- marketplaces['runwork'] = {
720
- source: { source: 'directory', path: marketRoot },
721
- installLocation: marketRoot,
722
- lastUpdated: new Date().toISOString(),
723
- };
724
- writeJsonConfig(marketplacesPath, marketplaces);
725
- console.log(` [Claude Code] ${wasRegistered ? 'Refreshed' : 'Registered'} plugin ` +
726
- `${pluginKey} v${PLUGIN_VERSION} -> ${installedPath}`);
727
- // Enable the plugin in settings.json
728
- const settingsPath = join(homedir(), '.claude', 'settings.json');
729
- const settings = readJsonConfig(settingsPath);
730
- if (!settings['enabledPlugins']) {
731
- settings['enabledPlugins'] = {};
732
- }
733
- const enabled = settings['enabledPlugins'];
734
- if (!enabled[`${PLUGIN_NAME}@runwork`]) {
735
- enabled[`${PLUGIN_NAME}@runwork`] = true;
736
- writeJsonConfig(settingsPath, settings);
737
- }
738
- }
739
- }
740
- /**
741
- * Remove old skill directory that used the display name (with spaces) if it
742
- * differs from the new slug-based directory name.
743
- */
744
- function cleanupOldSkillDir(baseDir, skill) {
745
- if (skill.name === skill.filename)
746
- return;
747
- const oldDir = join(baseDir, skill.name);
748
- if (existsSync(oldDir)) {
749
- try {
750
- rmSync(oldDir, { recursive: true, force: true });
751
- }
752
- catch { /* best-effort */ }
753
- }
754
- }