runwork 0.15.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/bundled-types/task-delegation/task-delegation/types.d.ts +6 -0
  2. package/dist/index.js +20237 -116
  3. package/package.json +4 -4
  4. package/dist/__tests__/curl-parser.test.d.ts +0 -1
  5. package/dist/__tests__/curl-parser.test.js +0 -250
  6. package/dist/__tests__/install-scripts.test.d.ts +0 -1
  7. package/dist/__tests__/install-scripts.test.js +0 -280
  8. package/dist/__tests__/types-manager.test.d.ts +0 -1
  9. package/dist/__tests__/types-manager.test.js +0 -89
  10. package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
  11. package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
  12. package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
  13. package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -105
  14. package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
  15. package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
  16. package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
  17. package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
  18. package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
  19. package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
  20. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
  21. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
  22. package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
  23. package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
  24. package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
  25. package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
  26. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
  27. package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
  28. package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
  29. package/dist/agents/__tests__/codex-instructions.test.js +0 -57
  30. package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
  31. package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
  32. package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
  33. package/dist/agents/__tests__/codex-stats.test.js +0 -370
  34. package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
  35. package/dist/agents/__tests__/cursor-merge.test.js +0 -66
  36. package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
  37. package/dist/agents/__tests__/cursor-stats.test.js +0 -183
  38. package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
  39. package/dist/agents/__tests__/defaults-merge.test.js +0 -268
  40. package/dist/agents/__tests__/detection.test.d.ts +0 -1
  41. package/dist/agents/__tests__/detection.test.js +0 -89
  42. package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
  43. package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
  44. package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
  45. package/dist/agents/__tests__/instruction-hint.test.js +0 -69
  46. package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
  47. package/dist/agents/__tests__/intro-skill.test.js +0 -193
  48. package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
  49. package/dist/agents/__tests__/schema-validation.test.js +0 -212
  50. package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
  51. package/dist/agents/__tests__/skill-slug.test.js +0 -77
  52. package/dist/agents/claude-code.d.ts +0 -59
  53. package/dist/agents/claude-code.js +0 -753
  54. package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
  55. package/dist/agents/claude-desktop-plugin-tree.js +0 -143
  56. package/dist/agents/claude-desktop.d.ts +0 -47
  57. package/dist/agents/claude-desktop.js +0 -684
  58. package/dist/agents/cline.d.ts +0 -15
  59. package/dist/agents/cline.js +0 -130
  60. package/dist/agents/codex.d.ts +0 -44
  61. package/dist/agents/codex.js +0 -453
  62. package/dist/agents/conversation-skills.d.ts +0 -18
  63. package/dist/agents/conversation-skills.js +0 -229
  64. package/dist/agents/cursor.d.ts +0 -35
  65. package/dist/agents/cursor.js +0 -294
  66. package/dist/agents/default-config.d.ts +0 -30
  67. package/dist/agents/default-config.js +0 -67
  68. package/dist/agents/defaults-merge.d.ts +0 -87
  69. package/dist/agents/defaults-merge.js +0 -150
  70. package/dist/agents/detect.d.ts +0 -4
  71. package/dist/agents/detect.js +0 -67
  72. package/dist/agents/detection.d.ts +0 -18
  73. package/dist/agents/detection.js +0 -94
  74. package/dist/agents/gemini.d.ts +0 -15
  75. package/dist/agents/gemini.js +0 -122
  76. package/dist/agents/generic-adapter.d.ts +0 -25
  77. package/dist/agents/generic-adapter.js +0 -151
  78. package/dist/agents/intro-skill.d.ts +0 -45
  79. package/dist/agents/intro-skill.js +0 -447
  80. package/dist/agents/registry-data.d.ts +0 -192
  81. package/dist/agents/registry-data.js +0 -669
  82. package/dist/agents/registry.d.ts +0 -13
  83. package/dist/agents/registry.js +0 -36
  84. package/dist/agents/runtime-detection.d.ts +0 -82
  85. package/dist/agents/runtime-detection.js +0 -271
  86. package/dist/agents/session-start-hook.d.ts +0 -37
  87. package/dist/agents/session-start-hook.js +0 -159
  88. package/dist/agents/types.d.ts +0 -171
  89. package/dist/agents/types.js +0 -75
  90. package/dist/agents/utils/instruction-hint.d.ts +0 -21
  91. package/dist/agents/utils/instruction-hint.js +0 -108
  92. package/dist/agents/utils/json-config.d.ts +0 -19
  93. package/dist/agents/utils/json-config.js +0 -69
  94. package/dist/agents/utils/toml-config.d.ts +0 -8
  95. package/dist/agents/utils/toml-config.js +0 -27
  96. package/dist/agents/windsurf.d.ts +0 -14
  97. package/dist/agents/windsurf.js +0 -102
  98. package/dist/api/__tests__/client.test.d.ts +0 -1
  99. package/dist/api/__tests__/client.test.js +0 -272
  100. package/dist/api/client.d.ts +0 -326
  101. package/dist/api/client.js +0 -427
  102. package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
  103. package/dist/auth/__tests__/login-flow.test.js +0 -101
  104. package/dist/auth/__tests__/store.test.d.ts +0 -1
  105. package/dist/auth/__tests__/store.test.js +0 -132
  106. package/dist/auth/login-flow.d.ts +0 -26
  107. package/dist/auth/login-flow.js +0 -137
  108. package/dist/auth/store.d.ts +0 -5
  109. package/dist/auth/store.js +0 -62
  110. package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
  111. package/dist/commands/__tests__/clone-args.test.js +0 -51
  112. package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
  113. package/dist/commands/__tests__/clone-source-result.test.js +0 -45
  114. package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
  115. package/dist/commands/__tests__/info-merge.test.js +0 -55
  116. package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
  117. package/dist/commands/__tests__/mcp-entries.test.js +0 -48
  118. package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
  119. package/dist/commands/__tests__/setup-persona.test.js +0 -31
  120. package/dist/commands/__tests__/setup.test.d.ts +0 -1
  121. package/dist/commands/__tests__/setup.test.js +0 -81
  122. package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
  123. package/dist/commands/__tests__/sync-redetect.test.js +0 -96
  124. package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
  125. package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
  126. package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
  127. package/dist/commands/__tests__/upgrade.test.js +0 -157
  128. package/dist/commands/agents.d.ts +0 -2
  129. package/dist/commands/agents.js +0 -160
  130. package/dist/commands/api-keys.d.ts +0 -2
  131. package/dist/commands/api-keys.js +0 -95
  132. package/dist/commands/apps.d.ts +0 -2
  133. package/dist/commands/apps.js +0 -82
  134. package/dist/commands/build-plugin.d.ts +0 -2
  135. package/dist/commands/build-plugin.js +0 -135
  136. package/dist/commands/clone.d.ts +0 -60
  137. package/dist/commands/clone.js +0 -271
  138. package/dist/commands/components.d.ts +0 -2
  139. package/dist/commands/components.js +0 -43
  140. package/dist/commands/deploy.d.ts +0 -2
  141. package/dist/commands/deploy.js +0 -279
  142. package/dist/commands/dev.d.ts +0 -11
  143. package/dist/commands/dev.js +0 -1011
  144. package/dist/commands/doctor.d.ts +0 -2
  145. package/dist/commands/doctor.js +0 -230
  146. package/dist/commands/endpoints.d.ts +0 -2
  147. package/dist/commands/endpoints.js +0 -189
  148. package/dist/commands/entities.d.ts +0 -2
  149. package/dist/commands/entities.js +0 -198
  150. package/dist/commands/files.d.ts +0 -2
  151. package/dist/commands/files.js +0 -193
  152. package/dist/commands/inbox.d.ts +0 -11
  153. package/dist/commands/inbox.js +0 -60
  154. package/dist/commands/info.d.ts +0 -178
  155. package/dist/commands/info.js +0 -455
  156. package/dist/commands/init.d.ts +0 -21
  157. package/dist/commands/init.js +0 -185
  158. package/dist/commands/integrations.d.ts +0 -2
  159. package/dist/commands/integrations.js +0 -233
  160. package/dist/commands/login.d.ts +0 -2
  161. package/dist/commands/login.js +0 -44
  162. package/dist/commands/logout.d.ts +0 -2
  163. package/dist/commands/logout.js +0 -13
  164. package/dist/commands/logs.d.ts +0 -2
  165. package/dist/commands/logs.js +0 -232
  166. package/dist/commands/mcp-entries.d.ts +0 -13
  167. package/dist/commands/mcp-entries.js +0 -26
  168. package/dist/commands/mcp.d.ts +0 -2
  169. package/dist/commands/mcp.js +0 -245
  170. package/dist/commands/open.d.ts +0 -2
  171. package/dist/commands/open.js +0 -53
  172. package/dist/commands/resume.d.ts +0 -2
  173. package/dist/commands/resume.js +0 -289
  174. package/dist/commands/save-convo.d.ts +0 -8
  175. package/dist/commands/save-convo.js +0 -20
  176. package/dist/commands/schedules.d.ts +0 -2
  177. package/dist/commands/schedules.js +0 -221
  178. package/dist/commands/setup.d.ts +0 -27
  179. package/dist/commands/setup.js +0 -177
  180. package/dist/commands/share-convo.d.ts +0 -24
  181. package/dist/commands/share-convo.js +0 -167
  182. package/dist/commands/skills.d.ts +0 -2
  183. package/dist/commands/skills.js +0 -352
  184. package/dist/commands/sync-telemetry.d.ts +0 -33
  185. package/dist/commands/sync-telemetry.js +0 -186
  186. package/dist/commands/sync.d.ts +0 -37
  187. package/dist/commands/sync.js +0 -702
  188. package/dist/commands/uninstall.d.ts +0 -2
  189. package/dist/commands/uninstall.js +0 -145
  190. package/dist/commands/upgrade.d.ts +0 -14
  191. package/dist/commands/upgrade.js +0 -217
  192. package/dist/commands/validate.d.ts +0 -2
  193. package/dist/commands/validate.js +0 -89
  194. package/dist/commands/welcome.d.ts +0 -1
  195. package/dist/commands/welcome.js +0 -86
  196. package/dist/commands/workflows.d.ts +0 -2
  197. package/dist/commands/workflows.js +0 -187
  198. package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
  199. package/dist/deploy/__tests__/deploy-state.test.js +0 -80
  200. package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
  201. package/dist/deploy/__tests__/deploy-status.test.js +0 -41
  202. package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
  203. package/dist/deploy/__tests__/detach-args.test.js +0 -30
  204. package/dist/deploy/deploy-state.d.ts +0 -36
  205. package/dist/deploy/deploy-state.js +0 -63
  206. package/dist/deploy/deploy-status.d.ts +0 -21
  207. package/dist/deploy/deploy-status.js +0 -36
  208. package/dist/deploy/detach.d.ts +0 -32
  209. package/dist/deploy/detach.js +0 -71
  210. package/dist/dev/__tests__/attach.test.d.ts +0 -1
  211. package/dist/dev/__tests__/attach.test.js +0 -296
  212. package/dist/dev/__tests__/detach.test.d.ts +0 -1
  213. package/dist/dev/__tests__/detach.test.js +0 -404
  214. package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
  215. package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
  216. package/dist/dev/__tests__/session.test.d.ts +0 -1
  217. package/dist/dev/__tests__/session.test.js +0 -446
  218. package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
  219. package/dist/dev/__tests__/startup-sync.test.js +0 -32
  220. package/dist/dev/__tests__/stop.test.d.ts +0 -1
  221. package/dist/dev/__tests__/stop.test.js +0 -172
  222. package/dist/dev/attach.d.ts +0 -120
  223. package/dist/dev/attach.js +0 -269
  224. package/dist/dev/detach.d.ts +0 -187
  225. package/dist/dev/detach.js +0 -292
  226. package/dist/dev/preview-url-poller.d.ts +0 -35
  227. package/dist/dev/preview-url-poller.js +0 -50
  228. package/dist/dev/session.d.ts +0 -175
  229. package/dist/dev/session.js +0 -258
  230. package/dist/dev/startup-sync.d.ts +0 -23
  231. package/dist/dev/startup-sync.js +0 -14
  232. package/dist/dev/stop.d.ts +0 -52
  233. package/dist/dev/stop.js +0 -101
  234. package/dist/devtools/registry-data.d.ts +0 -46
  235. package/dist/devtools/registry-data.js +0 -40
  236. package/dist/generated/bundled-types.d.ts +0 -1
  237. package/dist/generated/bundled-types.js +0 -46
  238. package/dist/generated/version.d.ts +0 -1
  239. package/dist/generated/version.js +0 -2
  240. package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
  241. package/dist/git/__tests__/auto-commit.test.js +0 -431
  242. package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
  243. package/dist/git/__tests__/classify-sync-error.test.js +0 -57
  244. package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
  245. package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
  246. package/dist/git/__tests__/credentials.test.d.ts +0 -1
  247. package/dist/git/__tests__/credentials.test.js +0 -141
  248. package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
  249. package/dist/git/__tests__/deploy-guard.test.js +0 -61
  250. package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
  251. package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
  252. package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
  253. package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
  254. package/dist/git/__tests__/identity.test.d.ts +0 -1
  255. package/dist/git/__tests__/identity.test.js +0 -146
  256. package/dist/git/__tests__/manifest.test.d.ts +0 -1
  257. package/dist/git/__tests__/manifest.test.js +0 -446
  258. package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
  259. package/dist/git/__tests__/preflight-resolution.test.js +0 -366
  260. package/dist/git/__tests__/preflight.test.d.ts +0 -1
  261. package/dist/git/__tests__/preflight.test.js +0 -36
  262. package/dist/git/__tests__/repo-config.test.d.ts +0 -1
  263. package/dist/git/__tests__/repo-config.test.js +0 -26
  264. package/dist/git/__tests__/sync.test.d.ts +0 -1
  265. package/dist/git/__tests__/sync.test.js +0 -405
  266. package/dist/git/auto-commit.d.ts +0 -35
  267. package/dist/git/auto-commit.js +0 -293
  268. package/dist/git/classify-sync-error.d.ts +0 -21
  269. package/dist/git/classify-sync-error.js +0 -111
  270. package/dist/git/credentials.d.ts +0 -75
  271. package/dist/git/credentials.js +0 -164
  272. package/dist/git/critical-files.d.ts +0 -20
  273. package/dist/git/critical-files.js +0 -68
  274. package/dist/git/deploy-guard.d.ts +0 -53
  275. package/dist/git/deploy-guard.js +0 -78
  276. package/dist/git/identity.d.ts +0 -44
  277. package/dist/git/identity.js +0 -133
  278. package/dist/git/preflight.d.ts +0 -57
  279. package/dist/git/preflight.js +0 -276
  280. package/dist/git/remote.d.ts +0 -37
  281. package/dist/git/remote.js +0 -75
  282. package/dist/git/repo-config.d.ts +0 -8
  283. package/dist/git/repo-config.js +0 -29
  284. package/dist/git/sync.d.ts +0 -15
  285. package/dist/git/sync.js +0 -159
  286. package/dist/health/__tests__/checks.test.d.ts +0 -1
  287. package/dist/health/__tests__/checks.test.js +0 -357
  288. package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
  289. package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
  290. package/dist/health/__tests__/fix.test.d.ts +0 -1
  291. package/dist/health/__tests__/fix.test.js +0 -72
  292. package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
  293. package/dist/health/__tests__/runner-filter.test.js +0 -61
  294. package/dist/health/checks.d.ts +0 -42
  295. package/dist/health/checks.js +0 -636
  296. package/dist/health/fix.d.ts +0 -22
  297. package/dist/health/fix.js +0 -62
  298. package/dist/health/runner.d.ts +0 -8
  299. package/dist/health/runner.js +0 -47
  300. package/dist/health/types.d.ts +0 -12
  301. package/dist/health/types.js +0 -1
  302. package/dist/index.d.ts +0 -1
  303. package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
  304. package/dist/logs/__tests__/tailer-format.test.js +0 -43
  305. package/dist/logs/tailer.d.ts +0 -17
  306. package/dist/logs/tailer.js +0 -217
  307. package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
  308. package/dist/sync/__tests__/change-detect.test.js +0 -123
  309. package/dist/sync/__tests__/hash.test.d.ts +0 -1
  310. package/dist/sync/__tests__/hash.test.js +0 -18
  311. package/dist/sync/change-detect.d.ts +0 -19
  312. package/dist/sync/change-detect.js +0 -136
  313. package/dist/sync/conflict-ui.d.ts +0 -5
  314. package/dist/sync/conflict-ui.js +0 -78
  315. package/dist/sync/executor.d.ts +0 -23
  316. package/dist/sync/executor.js +0 -102
  317. package/dist/sync/hash.d.ts +0 -1
  318. package/dist/sync/hash.js +0 -4
  319. package/dist/sync/types.d.ts +0 -24
  320. package/dist/sync/types.js +0 -1
  321. package/dist/template/manifest.d.ts +0 -17
  322. package/dist/template/manifest.js +0 -145
  323. package/dist/tools/types.d.ts +0 -52
  324. package/dist/tools/types.js +0 -8
  325. package/dist/types-manager.d.ts +0 -1
  326. package/dist/types-manager.js +0 -35
  327. package/dist/types.d.ts +0 -349
  328. package/dist/types.js +0 -1
  329. package/dist/ui/__tests__/banner.test.d.ts +0 -1
  330. package/dist/ui/__tests__/banner.test.js +0 -98
  331. package/dist/ui/__tests__/colors.test.d.ts +0 -1
  332. package/dist/ui/__tests__/colors.test.js +0 -22
  333. package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
  334. package/dist/ui/__tests__/keyboard.test.js +0 -34
  335. package/dist/ui/__tests__/status-line.test.d.ts +0 -1
  336. package/dist/ui/__tests__/status-line.test.js +0 -54
  337. package/dist/ui/banner.d.ts +0 -29
  338. package/dist/ui/banner.js +0 -153
  339. package/dist/ui/colors.d.ts +0 -4
  340. package/dist/ui/colors.js +0 -7
  341. package/dist/ui/keyboard.d.ts +0 -12
  342. package/dist/ui/keyboard.js +0 -61
  343. package/dist/ui/status-line.d.ts +0 -6
  344. package/dist/ui/status-line.js +0 -53
  345. package/dist/utils/__tests__/format-error.test.d.ts +0 -1
  346. package/dist/utils/__tests__/format-error.test.js +0 -43
  347. package/dist/utils/__tests__/help-json.test.d.ts +0 -1
  348. package/dist/utils/__tests__/help-json.test.js +0 -39
  349. package/dist/utils/__tests__/http.test.d.ts +0 -1
  350. package/dist/utils/__tests__/http.test.js +0 -381
  351. package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
  352. package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
  353. package/dist/utils/__tests__/output.test.d.ts +0 -1
  354. package/dist/utils/__tests__/output.test.js +0 -38
  355. package/dist/utils/__tests__/prompt.test.d.ts +0 -1
  356. package/dist/utils/__tests__/prompt.test.js +0 -27
  357. package/dist/utils/__tests__/resolve.test.d.ts +0 -1
  358. package/dist/utils/__tests__/resolve.test.js +0 -95
  359. package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
  360. package/dist/utils/__tests__/sqlite.test.js +0 -89
  361. package/dist/utils/agent-guidance.d.ts +0 -47
  362. package/dist/utils/agent-guidance.js +0 -128
  363. package/dist/utils/app-info.d.ts +0 -70
  364. package/dist/utils/app-info.js +0 -167
  365. package/dist/utils/curl-parser.d.ts +0 -12
  366. package/dist/utils/curl-parser.js +0 -162
  367. package/dist/utils/data-input.d.ts +0 -1
  368. package/dist/utils/data-input.js +0 -38
  369. package/dist/utils/format-error.d.ts +0 -10
  370. package/dist/utils/format-error.js +0 -38
  371. package/dist/utils/fs.d.ts +0 -5
  372. package/dist/utils/fs.js +0 -23
  373. package/dist/utils/help-json.d.ts +0 -70
  374. package/dist/utils/help-json.js +0 -88
  375. package/dist/utils/http.d.ts +0 -46
  376. package/dist/utils/http.js +0 -421
  377. package/dist/utils/ignore-matcher.d.ts +0 -47
  378. package/dist/utils/ignore-matcher.js +0 -132
  379. package/dist/utils/output.d.ts +0 -17
  380. package/dist/utils/output.js +0 -27
  381. package/dist/utils/prompt.d.ts +0 -5
  382. package/dist/utils/prompt.js +0 -42
  383. package/dist/utils/resolve.d.ts +0 -12
  384. package/dist/utils/resolve.js +0 -52
  385. package/dist/utils/setup-state.d.ts +0 -3
  386. package/dist/utils/setup-state.js +0 -19
  387. package/dist/utils/sqlite-adapter.d.ts +0 -48
  388. package/dist/utils/sqlite-adapter.js +0 -147
  389. package/dist/utils/sqlite.d.ts +0 -14
  390. package/dist/utils/sqlite.js +0 -14
  391. package/dist/utils/subprocess.d.ts +0 -19
  392. package/dist/utils/subprocess.js +0 -27
  393. package/dist/utils/which.d.ts +0 -14
  394. package/dist/utils/which.js +0 -47
  395. package/dist/utils/zip.d.ts +0 -7
  396. package/dist/utils/zip.js +0 -42
  397. package/dist/validate/__tests__/validate.test.d.ts +0 -1
  398. package/dist/validate/__tests__/validate.test.js +0 -42
  399. package/dist/validate/freshness.d.ts +0 -28
  400. package/dist/validate/freshness.js +0 -48
  401. package/dist/validate/preview.d.ts +0 -21
  402. package/dist/validate/preview.js +0 -39
  403. package/dist/workspace/resolve.d.ts +0 -19
  404. package/dist/workspace/resolve.js +0 -100
@@ -1,702 +0,0 @@
1
- import { Command } from 'commander';
2
- import { readFileSync, writeFileSync, existsSync } from 'fs';
3
- import { join } from 'path';
4
- import { homedir } from 'os';
5
- import { requireAuth } from '../auth/store.js';
6
- import { ApiClient } from '../api/client.js';
7
- import { getAdapterBySlug, detectAgents } from '../agents/detect.js';
8
- import { CodexAdapter } from '../agents/codex.js';
9
- import { RUNWORK_MCP_PREFIX, RUNWORK_WORKSPACE_MCP_NAME } from '../agents/types.js';
10
- import { buildExternalMcpEntries } from './mcp-entries.js';
11
- import { RUNWORK_AGENT_DEFAULTS, AGENT_DEFAULTS_SCHEMA_VERSION } from '../agents/default-config.js';
12
- import { resolveAgentDefaults } from '../agents/defaults-merge.js';
13
- import { collectTelemetryEvents, printTelemetryVerbose, summarizeTelemetryForDryRun, } from './sync-telemetry.js';
14
- import { generateIntroSkill, generateInstructionHint, buildAppSkillDescription } from '../agents/intro-skill.js';
15
- import { buildShareConversationSkill, buildSaveConversationSkill, BUILT_IN_SKILL_NAMES } from '../agents/conversation-skills.js';
16
- import { computeSyncPlan } from '../sync/change-detect.js';
17
- import { printSyncSummary, resolveConflict, resolveConflictNonInteractive } from '../sync/conflict-ui.js';
18
- import { executeSyncPlan } from '../sync/executor.js';
19
- import { getRegistryAgent, resolveToAbsolute, isConnectOnlyAgent } from '../agents/registry.js';
20
- function loadSetupState(filePath) {
21
- if (!existsSync(filePath))
22
- return null;
23
- try {
24
- return JSON.parse(readFileSync(filePath, 'utf-8'));
25
- }
26
- catch {
27
- return null;
28
- }
29
- }
30
- /**
31
- * Read local skill content from the first configured agent's skill directory.
32
- */
33
- function readLocalSkills(state) {
34
- const results = [];
35
- if (!state.skills || state.skills.length === 0)
36
- return results;
37
- for (const slug of state.configuredAgents) {
38
- const def = getRegistryAgent(slug);
39
- if (!def?.skillsPaths)
40
- continue;
41
- const useScope = state.scope === 'both' ? 'user' : state.scope;
42
- const pathTemplate = useScope === 'project' ? def.skillsPaths.project : def.skillsPaths.global;
43
- if (!pathTemplate)
44
- continue;
45
- const baseDir = resolveToAbsolute(pathTemplate, useScope === 'project' ? 'project' : 'global');
46
- if (!baseDir)
47
- continue;
48
- for (const skillName of state.skills) {
49
- // Try SKILL.md in subdirectory
50
- const skillMdPath = join(baseDir, skillName, 'SKILL.md');
51
- if (existsSync(skillMdPath)) {
52
- results.push({ name: skillName, content: readFileSync(skillMdPath, 'utf-8') });
53
- continue;
54
- }
55
- // Try flat file
56
- const filename = skillName.toLowerCase().replace(/[^a-z0-9]+/g, '-');
57
- const flatPath = join(baseDir, `${filename}.md`);
58
- if (existsSync(flatPath)) {
59
- results.push({ name: skillName, content: readFileSync(flatPath, 'utf-8') });
60
- }
61
- }
62
- if (results.length > 0)
63
- break;
64
- }
65
- return results;
66
- }
67
- /**
68
- * How long a detection result stays trusted before sync re-runs detection
69
- * on its own. Detection is cheap on macOS/Linux but pays a PowerShell
70
- * waterfall on Windows, so we cache for a day. Users who just installed
71
- * a new agent can shortcut the wait via `--redetect` (or the desktop's
72
- * "Rescan" button, which forwards the flag).
73
- */
74
- export const REDETECT_TTL_MS = 24 * 60 * 60 * 1000;
75
- /**
76
- * Decide whether to re-run installation detection for this sync. We always
77
- * re-detect on explicit user request, on first sync (no timestamp yet), when
78
- * setup ended up with zero agents (recovery), or after the TTL has lapsed.
79
- */
80
- export function shouldRedetect(state, opts) {
81
- if (opts.redetect)
82
- return true;
83
- if (state.configuredAgents.length === 0)
84
- return true;
85
- if (!state.lastDetectedAt)
86
- return true;
87
- const last = Date.parse(state.lastDetectedAt);
88
- if (Number.isNaN(last))
89
- return true;
90
- return Date.now() - last > REDETECT_TTL_MS;
91
- }
92
- /**
93
- * Detect installed agents and merge any new slugs into `state.configuredAgents`.
94
- * Never removes agents — a transient PATH glitch shouldn't wipe the setup.
95
- * Returns the slugs that were newly added (for logging).
96
- */
97
- export async function refreshConfiguredAgents(state) {
98
- const detected = await detectAgents();
99
- const before = new Set(state.configuredAgents);
100
- const added = [];
101
- for (const adapter of detected) {
102
- if (!before.has(adapter.slug)) {
103
- state.configuredAgents.push(adapter.slug);
104
- added.push(adapter.slug);
105
- }
106
- }
107
- state.lastDetectedAt = new Date().toISOString();
108
- return added;
109
- }
110
- export async function syncFromState(state, statePath, credentials, opts) {
111
- const client = new ApiClient(credentials);
112
- // Refresh workspace name/slug if missing or stale (e.g. setup ran before name was set)
113
- if (!state.workspaceName || state.workspaceName === state.workspaceId || !state.workspaceSlug) {
114
- try {
115
- const workspaces = await client.listWorkspaces();
116
- const ws = workspaces.find(w => w.id === state.workspaceId);
117
- if (ws?.name)
118
- state.workspaceName = ws.name;
119
- if (ws?.slug)
120
- state.workspaceSlug = ws.slug;
121
- }
122
- catch {
123
- // Best-effort, keep existing values
124
- }
125
- }
126
- console.log(`Syncing workspace: ${state.workspaceName || state.workspaceId}`);
127
- // Refresh the configured-agents list when the cached detection is stale,
128
- // empty, or the user explicitly asked. This is what catches "I just installed
129
- // Claude Code on this machine" without needing the user to re-run setup.
130
- if (shouldRedetect(state, opts)) {
131
- console.log(' Detecting installed agents...');
132
- const added = await refreshConfiguredAgents(state);
133
- if (added.length > 0) {
134
- console.log(` Detected new agent${added.length > 1 ? 's' : ''}: ${added.join(', ')}`);
135
- }
136
- }
137
- console.log(' Fetching workspace data...');
138
- // Fetch latest data (includeContent=true gets all skill content in one request)
139
- const [allSkills, mcpServers, externalSkills, registries, connectedIntegrations, resolvedMcpCredentials] = await Promise.all([
140
- client.listWorkspaceSkills(state.workspaceId, true),
141
- client.listMcpServers(state.workspaceId),
142
- client.listExternalSkills(state.workspaceId),
143
- client.getWorkspaceAll(state.workspaceId).catch(() => null),
144
- client.listConnectedIntegrations(state.workspaceId)
145
- .then(list => list.map(i => i.canonicalId ?? i.integrationId))
146
- .catch(() => []),
147
- // Decrypted auth headers for header-auth servers, scoped to this user.
148
- // Tolerate older backends that lack the endpoint.
149
- client.resolveMcpCredentials(state.workspaceId).catch(() => ({})),
150
- ]);
151
- const appCount = allSkills.filter(s => s.type === 'app').length;
152
- const parts = [];
153
- if (appCount > 0)
154
- parts.push(`${appCount} app${appCount > 1 ? 's' : ''}`);
155
- if (externalSkills.length > 0)
156
- parts.push(`${externalSkills.length} skill${externalSkills.length > 1 ? 's' : ''}`);
157
- if (mcpServers.length > 0)
158
- parts.push(`${mcpServers.filter(s => s.enabled).length} MCP server${mcpServers.filter(s => s.enabled).length > 1 ? 's' : ''}`);
159
- if (connectedIntegrations.length > 0)
160
- parts.push(`${connectedIntegrations.length} integration${connectedIntegrations.length > 1 ? 's' : ''}`);
161
- if (registries) {
162
- if (registries.entities.length > 0)
163
- parts.push(`${registries.entities.length} entit${registries.entities.length > 1 ? 'ies' : 'y'}`);
164
- if (registries.workflows.length > 0)
165
- parts.push(`${registries.workflows.length} workflow${registries.workflows.length > 1 ? 's' : ''}`);
166
- if (registries.agents.length > 0)
167
- parts.push(`${registries.agents.length} agent${registries.agents.length > 1 ? 's' : ''}`);
168
- }
169
- if (parts.length > 0) {
170
- console.log(` Found: ${parts.join(', ')}`);
171
- }
172
- // Build MCP entries (pull-only)
173
- const baseUrl = credentials.baseUrl || 'https://runwork.ai';
174
- const mcpEntries = buildExternalMcpEntries(mcpServers, resolvedMcpCredentials);
175
- mcpEntries.push({
176
- name: RUNWORK_WORKSPACE_MCP_NAME,
177
- url: `${baseUrl}/api/workspaces/${state.workspaceId}/mcp`,
178
- transport: 'streamable-http',
179
- headers: { Authorization: `Bearer ${credentials.apiKey}` },
180
- description: 'Runwork workspace tools: query entities, trigger workflows, manage integrations, run agents, and access shared data across your team\'s apps.',
181
- });
182
- // Build remote skills list
183
- const remoteSkills = [];
184
- for (const s of externalSkills) {
185
- remoteSkills.push({ name: s.name, content: s.content, source: 'external', remoteId: s.id });
186
- }
187
- for (const s of allSkills) {
188
- if (s.type === 'app' && s.appId && s.content?.trim()) {
189
- remoteSkills.push({ name: s.name, content: s.content, source: 'app', appId: s.appId });
190
- }
191
- }
192
- // Read local skills for change detection
193
- const localSkills = readLocalSkills(state);
194
- // Built-in skills (shipped by the CLI from code) are CANONICAL: they
195
- // are never pushed to the workspace and never pulled from it. The diff
196
- // engine must not see them at all -- if it did, a workspace skill that
197
- // happens to share a name (e.g. someone uploaded `share-conversation`
198
- // manually) would either push the built-in upstream or pull the stale
199
- // workspace copy on top, both wrong. Filter both sides before the diff.
200
- const builtInNameSet = new Set(BUILT_IN_SKILL_NAMES);
201
- const collidingRemote = remoteSkills.filter(s => builtInNameSet.has(s.name));
202
- if (collidingRemote.length > 0) {
203
- console.log(`\n Warning: ${collidingRemote.length} workspace skill${collidingRemote.length === 1 ? '' : 's'} ` +
204
- `shadow${collidingRemote.length === 1 ? 's' : ''} built-in CLI skill${collidingRemote.length === 1 ? '' : 's'}: ` +
205
- `${collidingRemote.map(s => s.name).join(', ')}. The CLI built-in versions will be used locally; ` +
206
- `the workspace copies are stale duplicates and can be safely deleted from the dashboard.`);
207
- }
208
- const localSkillsForDiff = localSkills.filter(s => !builtInNameSet.has(s.name));
209
- const remoteSkillsForDiff = remoteSkills.filter(s => !builtInNameSet.has(s.name));
210
- // Compute sync plan
211
- const plan = computeSyncPlan({
212
- storedHashes: state.skillHashes || {},
213
- localSkills: localSkillsForDiff,
214
- remoteSkills: remoteSkillsForDiff,
215
- });
216
- // In pull-only mode, move pushes and conflicts to skips
217
- if (opts.pullOnly) {
218
- plan.skips.push(...plan.pushes.map(p => ({ ...p, action: 'skip' })));
219
- plan.pushes = [];
220
- plan.skips.push(...plan.conflicts.map(c => ({ ...c, action: 'skip' })));
221
- plan.conflicts = [];
222
- }
223
- // Display summary
224
- const hasChanges = plan.pulls.length > 0 || plan.pushes.length > 0 || plan.conflicts.length > 0 || plan.deletions.length > 0;
225
- if (hasChanges) {
226
- printSyncSummary(plan);
227
- }
228
- else {
229
- console.log(' All skills up to date.');
230
- }
231
- // Build adapters early so telemetry collection works in both dry-run and real paths
232
- const adapters = [];
233
- for (const slug of state.configuredAgents) {
234
- const adapter = getAdapterBySlug(slug);
235
- if (adapter)
236
- adapters.push(adapter);
237
- }
238
- if (opts.dryRun) {
239
- try {
240
- const telemetry = await collectTelemetryEvents({
241
- adapters,
242
- state,
243
- syncedSkillsCount: remoteSkills.length,
244
- syncedMcpServersCount: mcpEntries.length,
245
- teamInstructionsApplied: false,
246
- agentConfigsApplied: 0,
247
- });
248
- if (opts.verbose) {
249
- printTelemetryVerbose(telemetry);
250
- }
251
- else {
252
- console.log(`\n ${summarizeTelemetryForDryRun(telemetry)}`);
253
- }
254
- }
255
- catch {
256
- // Telemetry preview is best-effort
257
- }
258
- return;
259
- }
260
- // Resolve conflicts
261
- const resolvedConflicts = new Map();
262
- for (const conflict of plan.conflicts) {
263
- if (opts.yes || !process.stdout.isTTY) {
264
- const nonInteractiveResolution = resolveConflictNonInteractive(opts.prefer || 'remote');
265
- if (nonInteractiveResolution !== 'skip') {
266
- resolvedConflicts.set(conflict.name, nonInteractiveResolution);
267
- }
268
- }
269
- else {
270
- const resolution = await resolveConflict(conflict);
271
- if (resolution !== 'skip') {
272
- resolvedConflicts.set(conflict.name, resolution);
273
- }
274
- }
275
- }
276
- const scopes = state.scope === 'both' ? ['project', 'user'] : [state.scope];
277
- if (adapters.length > 0) {
278
- console.log(` Syncing to: ${adapters.map(a => a.name).join(', ')}`);
279
- }
280
- // Execute skill sync plan
281
- const newHashes = await executeSyncPlan(plan, resolvedConflicts, {
282
- client,
283
- workspaceId: state.workspaceId,
284
- adapters,
285
- scopes,
286
- hasMcp: mcpEntries.length > 0,
287
- });
288
- // Write intro skill, MCP configs, instruction hints (pull-only)
289
- const introSkill = generateIntroSkill({
290
- workspaceName: state.workspaceName || state.workspaceId,
291
- workspaceId: state.workspaceId,
292
- workspaceSlug: state.workspaceSlug,
293
- registries,
294
- connectedIntegrations,
295
- mcpServerCount: mcpEntries.length,
296
- skillCount: remoteSkills.length,
297
- mcpServerNames: mcpEntries.map(e => e.name.replace(RUNWORK_MCP_PREFIX, '')),
298
- skillNames: remoteSkills.map(s => s.name),
299
- });
300
- const instructionHint = generateInstructionHint({
301
- workspaceName: state.workspaceName || state.workspaceId,
302
- workspaceId: state.workspaceId,
303
- workspaceSlug: state.workspaceSlug,
304
- registries,
305
- connectedIntegrations,
306
- appCount: allSkills.filter(s => s.type === 'app').length,
307
- skillCount: remoteSkills.length,
308
- mcpServerCount: mcpEntries.length,
309
- persona: state.persona,
310
- });
311
- // For project scope: determine which app skill to include (only current app's skill)
312
- let projectAppSkillFilter = null;
313
- if (existsSync('.runwork.json')) {
314
- try {
315
- const config = JSON.parse(readFileSync('.runwork.json', 'utf-8'));
316
- if (config.appName) {
317
- projectAppSkillFilter = config.appName.toLowerCase().replace(/[^a-z0-9]+/g, '-');
318
- }
319
- }
320
- catch { /* ignore */ }
321
- }
322
- // Built-in skills shipped by the CLI on every sync. Named upfront so we can
323
- // surface them by name in the per-adapter sync log -- helps users (and
324
- // their agents) confirm that /runwork, /share-conversation, etc. landed.
325
- const builtInSkills = [
326
- introSkill,
327
- buildShareConversationSkill(),
328
- buildSaveConversationSkill(),
329
- ];
330
- const builtInNames = builtInSkills.map(s => s.name);
331
- // Counters surfaced at the end of the sync as a one-line summary so the
332
- // user can see at a glance how much actually got written this run.
333
- const summary = {
334
- adaptersProcessed: 0,
335
- adaptersFailed: 0,
336
- skillWrites: 0,
337
- skillFilesWritten: 0,
338
- mcpServerWrites: 0,
339
- instructionHintWrites: 0,
340
- hookInstallCalls: 0,
341
- };
342
- for (const adapter of adapters) {
343
- // Connect-only agents (e.g. ChatGPT) have no local files to write; the
344
- // connector lives in the user's account. Skip all local-write phases.
345
- if (isConnectOnlyAgent(getRegistryAgent(adapter.slug))) {
346
- console.log(` [${adapter.name}] Connect-only agent: no local files to sync`);
347
- summary.adaptersProcessed++;
348
- continue;
349
- }
350
- let adapterFailedAnyScope = false;
351
- for (const scope of scopes) {
352
- try {
353
- // Write skills: for project scope, filter to only the current app's skill.
354
- // When MCP servers are configured for this adapter, skip app-sourced skills
355
- // since the MCP server already exposes them as skill_* tools. Writing both
356
- // causes duplicate entries in the agent's skill listing.
357
- if (adapter.supportsSkills()) {
358
- const skipAppSkills = adapter.mcpProvidesSkills && mcpEntries.length > 0;
359
- const scopeSkills = remoteSkills.filter(s => {
360
- // Built-in CLI skills are written from the canonical built-in array
361
- // below; a workspace skill with the same name is a shadow that
362
- // would overwrite the built-in if we let it through. Skip it.
363
- if (builtInNameSet.has(s.name))
364
- return false;
365
- // App-sourced skills are already available via MCP skill_* tools
366
- if (skipAppSkills && s.source === 'app')
367
- return false;
368
- if (scope === 'project' && s.source === 'app' && projectAppSkillFilter) {
369
- const filename = s.name.toLowerCase().replace(/[^a-z0-9]+/g, '-');
370
- return filename === projectAppSkillFilter;
371
- }
372
- return true;
373
- });
374
- const workspaceSkillFiles = scopeSkills.map(s => ({
375
- name: s.name,
376
- filename: s.name.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
377
- content: s.content,
378
- description: s.source === 'app'
379
- ? (buildAppSkillDescription(s.name, registries) || `${s.name} - Runwork workspace application`)
380
- : `${s.name} - Runwork workspace skill`,
381
- }));
382
- const allSkillFiles = [...builtInSkills, ...workspaceSkillFiles];
383
- await adapter.writeSkills(allSkillFiles, scope);
384
- summary.skillWrites++;
385
- summary.skillFilesWritten += allSkillFiles.length;
386
- console.log(` [${adapter.name}] Wrote ${allSkillFiles.length} skills (${scope}): ` +
387
- `${builtInSkills.length} built-in [${builtInNames.join(', ')}], ` +
388
- `${workspaceSkillFiles.length} workspace`);
389
- }
390
- else {
391
- console.log(` [${adapter.name}] Skipped skills (${scope}): adapter does not support skills`);
392
- }
393
- // Write MCP configs
394
- if (adapter.supportsMcpScope(scope) && mcpEntries.length > 0) {
395
- await adapter.writeMcpServers(mcpEntries, scope);
396
- summary.mcpServerWrites++;
397
- console.log(` [${adapter.name}] Updated ${mcpEntries.length} MCP server${mcpEntries.length > 1 ? 's' : ''} (${scope})`);
398
- }
399
- else if (mcpEntries.length === 0) {
400
- console.log(` [${adapter.name}] Skipped MCP servers (${scope}): no workspace MCP servers configured`);
401
- }
402
- else if (!adapter.supportsMcpScope(scope)) {
403
- console.log(` [${adapter.name}] Skipped MCP servers (${scope}): adapter does not support MCP at this scope`);
404
- }
405
- // Write instruction hint
406
- await adapter.writeInstructionHint(instructionHint, scope);
407
- summary.instructionHintWrites++;
408
- console.log(` [${adapter.name}] Updated instruction hints (${scope})`);
409
- // Install built-in hooks (Claude Code's SessionStart, etc.). Called
410
- // after writeSkills so the plugin tree already exists. Skipped by
411
- // adapters that don't implement it.
412
- if (adapter.writeBuiltInHooks) {
413
- await adapter.writeBuiltInHooks(scope);
414
- summary.hookInstallCalls++;
415
- }
416
- }
417
- catch (err) {
418
- adapterFailedAnyScope = true;
419
- console.warn(` [${adapter.name}] Failed (${scope}): ${err instanceof Error ? err.message : err}`);
420
- }
421
- }
422
- summary.adaptersProcessed++;
423
- if (adapterFailedAnyScope)
424
- summary.adaptersFailed++;
425
- }
426
- // Pull team config from server. A failure here must not stop the
427
- // unified user-scope write below, which applies network and minimum-permission
428
- // floors regardless of whether team config was fetched.
429
- let teamInstructionsApplied = false;
430
- let agentConfigsApplied = 0;
431
- let teamInstructions;
432
- let agentConfigs;
433
- try {
434
- const onboardingConfig = await client.getOnboardingConfig(state.workspaceId);
435
- teamInstructions = onboardingConfig?.config?.teamInstructions ?? undefined;
436
- agentConfigs = onboardingConfig?.config?.agentConfigs ?? undefined;
437
- }
438
- catch {
439
- // Team config pull is non-fatal — proceed with no team-managed overrides.
440
- }
441
- // Write team instructions and/or per-agent extra instructions.
442
- for (const adapter of adapters) {
443
- if (isConnectOnlyAgent(getRegistryAgent(adapter.slug)))
444
- continue;
445
- if (!adapter.writeTeamInstructions)
446
- continue;
447
- const agentExtra = agentConfigs?.[adapter.slug]?.extraInstructions;
448
- const parts = [teamInstructions, agentExtra].filter(Boolean);
449
- if (parts.length === 0)
450
- continue;
451
- const fullInstructions = parts.join('\n\n');
452
- for (const scope of scopes) {
453
- try {
454
- await adapter.writeTeamInstructions(fullInstructions, scope);
455
- teamInstructionsApplied = true;
456
- console.log(` [${adapter.name}] Updated team instructions (${scope})`);
457
- }
458
- catch {
459
- // Best-effort per adapter/scope
460
- }
461
- }
462
- }
463
- // Apply per-agent project-scope config (team overrides only).
464
- // User scope is handled below in the unified defaults+network+minimum block.
465
- if (agentConfigs) {
466
- for (const adapter of adapters) {
467
- if (isConnectOnlyAgent(getRegistryAgent(adapter.slug)))
468
- continue;
469
- const agentConfig = agentConfigs[adapter.slug];
470
- if (!agentConfig || !adapter.writeAgentConfig)
471
- continue;
472
- const { extraInstructions: _, ...configWithoutInstructions } = agentConfig;
473
- if (Object.keys(configWithoutInstructions).length === 0)
474
- continue;
475
- for (const scope of scopes) {
476
- if (scope === 'user')
477
- continue; // handled in unified block below
478
- try {
479
- await adapter.writeAgentConfig(configWithoutInstructions, scope);
480
- agentConfigsApplied++;
481
- const configKeys = Object.keys(configWithoutInstructions).join(', ');
482
- console.log(` [${adapter.name}] Updated agent config: ${configKeys} (${scope})`);
483
- }
484
- catch {
485
- // Best-effort per adapter/scope
486
- }
487
- }
488
- }
489
- }
490
- // Unified user-scope write: merge baked defaults with team config, network
491
- // allowlist, and minimum permissions into a single writeAgentConfig call
492
- // per adapter. The merge layer tracks injected defaults in state.agentDefaults
493
- // so user-removed entries become sticky opt-outs.
494
- if (scopes.includes('user')) {
495
- const networkDomains = ['runwork.ai', '*.runwork.ai'];
496
- try {
497
- const baseHost = new URL(baseUrl).hostname;
498
- if (baseHost !== 'runwork.ai' && !baseHost.endsWith('.runwork.ai')) {
499
- networkDomains.push(baseHost, `*.${baseHost}`);
500
- }
501
- }
502
- catch { /* use defaults */ }
503
- // Order arrays list each agent's valid values from most restrictive to most
504
- // permissive. The floor logic upgrades anything strictly below `minimum`,
505
- // including unknown values (-1 < minimumIdx). That makes it critical to
506
- // include the agent's most-permissive option in `order` — otherwise a user
507
- // who explicitly set, say, `sandbox_mode = "danger-full-access"` gets
508
- // silently downgraded to `workspace-write`.
509
- const minimumPermissions = [
510
- { field: 'approval_policy', order: ['untrusted', 'on-request', 'on-failure', 'never'], minimum: 'on-request' },
511
- { field: 'sandbox_mode', order: ['read-only', 'workspace-write', 'danger-full-access'], minimum: 'workspace-write' },
512
- ];
513
- // agentDefaults lifecycle: full `runwork uninstall` deletes ~/.runwork
514
- // (state and all per-agent defaults state with it). Re-running `runwork
515
- // setup` overwrites setup.json without agentDefaults so every remaining
516
- // tool bootstraps fresh on the next sync. refreshConfiguredAgents only
517
- // adds slugs (never removes), so we don't need orphan-entry pruning here.
518
- if (!state.agentDefaults)
519
- state.agentDefaults = {};
520
- for (const adapter of adapters) {
521
- if (isConnectOnlyAgent(getRegistryAgent(adapter.slug)))
522
- continue;
523
- if (!adapter.writeAgentConfig)
524
- continue;
525
- const slug = adapter.slug;
526
- const baked = RUNWORK_AGENT_DEFAULTS[slug];
527
- const agentState = state.agentDefaults[slug];
528
- const team = agentConfigs?.[slug];
529
- // onDisk = undefined signals "removal detection is not possible" — used for
530
- // markerless adapters (Cursor) and for any adapter without readManagedBlock.
531
- // The resolver treats undefined differently from an empty array: it skips
532
- // opt-out fabrication entirely and trusts the baseline mechanism in the
533
- // adapter to preserve user edits via subtraction.
534
- let onDisk;
535
- if (baked && adapter.readManagedBlock) {
536
- try {
537
- onDisk = await adapter.readManagedBlock('user');
538
- }
539
- catch {
540
- onDisk = undefined;
541
- }
542
- }
543
- const resolved = resolveAgentDefaults({
544
- baked,
545
- state: agentState,
546
- onDisk,
547
- team: team?.permissionRules,
548
- });
549
- const mergedConfig = {
550
- modelPreference: team?.modelPreference,
551
- permissionRules: (resolved.managedAllow.length || resolved.managedDeny.length || team?.permissionRules?.defaultMode)
552
- ? {
553
- ...(resolved.managedAllow.length ? { allow: resolved.managedAllow } : {}),
554
- ...(resolved.managedDeny.length ? { deny: resolved.managedDeny } : {}),
555
- ...(team?.permissionRules?.defaultMode ? { defaultMode: team.permissionRules.defaultMode } : {}),
556
- }
557
- : undefined,
558
- networkAllowlist: networkDomains,
559
- minimumPermissions,
560
- };
561
- try {
562
- const baseline = agentState?.lastInjected;
563
- await adapter.writeAgentConfig(mergedConfig, 'user', baseline);
564
- if (baked) {
565
- const nextState = {
566
- lastInjected: {
567
- allow: resolved.applicableAllow,
568
- deny: resolved.applicableDeny,
569
- },
570
- userOptOuts: {
571
- allow: resolved.newOptOutsAllow,
572
- deny: resolved.newOptOutsDeny,
573
- },
574
- };
575
- state.agentDefaults[slug] = nextState;
576
- // Diagnostic log line (per "invisible / sync log only" policy)
577
- if (resolved.bootstrapped) {
578
- console.log(` [${adapter.name}] Bootstrapped default-rule tracking (defaults apply on next sync)`);
579
- }
580
- else if (resolved.applicableAllow.length || resolved.applicableDeny.length || resolved.removalsThisSync.allow || resolved.removalsThisSync.deny) {
581
- const totalRemovals = resolved.removalsThisSync.allow + resolved.removalsThisSync.deny;
582
- const removalNote = totalRemovals > 0
583
- ? ` (${totalRemovals} new opt-out${totalRemovals > 1 ? 's' : ''} honored)`
584
- : '';
585
- console.log(` [${adapter.name}] Applied defaults: ${resolved.applicableAllow.length} allow, ${resolved.applicableDeny.length} deny${removalNote}`);
586
- }
587
- }
588
- if (team)
589
- agentConfigsApplied++;
590
- }
591
- catch {
592
- // Best-effort per adapter
593
- }
594
- }
595
- state.agentDefaultsVersion = AGENT_DEFAULTS_SCHEMA_VERSION;
596
- }
597
- // Register ~/.runwork as a project in the Codex desktop app (best-effort).
598
- // Only attempts when Codex adapter is configured and the desktop app is closed.
599
- for (const adapter of adapters) {
600
- if (adapter instanceof CodexAdapter) {
601
- const runworkDir = join(homedir(), '.runwork');
602
- const result = adapter.registerDesktopWorkspace(runworkDir, 'Runwork');
603
- if (result === 'written') {
604
- console.log(` [${adapter.name}] Registered workspace in Codex desktop app`);
605
- }
606
- // 'app_running' and 'already_registered' are silently skipped
607
- break;
608
- }
609
- }
610
- // Update state
611
- state.lastSyncAt = new Date().toISOString();
612
- state.mcpServers = mcpEntries.map(e => e.name);
613
- state.skills = remoteSkills.map(s => s.name);
614
- state.skillFilenames = [
615
- 'runwork', // intro skill is always synced
616
- ...remoteSkills.map(s => s.name.toLowerCase().replace(/[^a-z0-9]+/g, '-')),
617
- ];
618
- // Merge hashes: keep existing for skips, update for everything else
619
- const mergedHashes = { ...(state.skillHashes || {}) };
620
- for (const [name, hash] of Object.entries(newHashes)) {
621
- mergedHashes[name] = hash;
622
- }
623
- // Remove deleted skills
624
- for (const del of plan.deletions) {
625
- delete mergedHashes[del.name];
626
- }
627
- state.skillHashes = mergedHashes;
628
- writeFileSync(statePath, JSON.stringify(state, null, 2));
629
- // Report telemetry (non-fatal)
630
- try {
631
- const telemetry = await collectTelemetryEvents({
632
- adapters,
633
- state,
634
- syncedSkillsCount: remoteSkills.length,
635
- syncedMcpServersCount: mcpEntries.length,
636
- teamInstructionsApplied,
637
- agentConfigsApplied,
638
- });
639
- if (opts.verbose)
640
- printTelemetryVerbose(telemetry);
641
- await client.reportTelemetry(state.workspaceId, telemetry.events);
642
- if (telemetry.healthReported)
643
- state.lastHealthReportAt = new Date().toISOString();
644
- state.reportedAgentSlugs = [
645
- ...new Set([...(state.reportedAgentSlugs ?? []), ...telemetry.newlyReportedAgents]),
646
- ];
647
- writeFileSync(statePath, JSON.stringify(state, null, 2));
648
- }
649
- catch {
650
- // Telemetry failures are non-fatal
651
- }
652
- // One-line summary so the user (and any agent reading sync output) can
653
- // see at a glance what got written this run, without scrolling the whole
654
- // per-adapter log.
655
- const summaryParts = [];
656
- summaryParts.push(`${summary.adaptersProcessed} adapter${summary.adaptersProcessed === 1 ? '' : 's'}`);
657
- if (summary.adaptersFailed > 0)
658
- summaryParts.push(`${summary.adaptersFailed} failed`);
659
- summaryParts.push(`${summary.skillWrites} skill write${summary.skillWrites === 1 ? '' : 's'} (${summary.skillFilesWritten} files)`);
660
- if (summary.mcpServerWrites > 0)
661
- summaryParts.push(`${summary.mcpServerWrites} MCP config write${summary.mcpServerWrites === 1 ? '' : 's'}`);
662
- if (summary.hookInstallCalls > 0)
663
- summaryParts.push(`${summary.hookInstallCalls} hook install${summary.hookInstallCalls === 1 ? '' : 's'}`);
664
- summaryParts.push(`${summary.instructionHintWrites} instruction hint write${summary.instructionHintWrites === 1 ? '' : 's'}`);
665
- console.log(`\n Summary: ${summaryParts.join(', ')}.`);
666
- }
667
- export const syncCommand = new Command('sync')
668
- .description('Sync skills bidirectionally and refresh MCP configs from workspace')
669
- .option('--dry-run', 'Show what would change without doing anything (includes telemetry preview)')
670
- .option('-v, --verbose', 'Print per-adapter stats and the telemetry envelope')
671
- .option('--pull-only', 'Only pull remote changes, never push local edits')
672
- .option('--prefer <side>', 'Auto-resolve conflicts: "local" or "remote" (implies --yes)')
673
- .option('-y, --yes', 'Non-interactive mode (default: prefer remote for conflicts)')
674
- .option('--redetect', 'Force agent-installation re-detection (picks up agents installed since last setup)')
675
- .action(async (opts) => {
676
- const credentials = requireAuth();
677
- const syncOpts = {
678
- dryRun: !!opts.dryRun,
679
- pullOnly: !!opts.pullOnly,
680
- yes: !!opts.yes || !!opts.prefer,
681
- prefer: opts.prefer,
682
- verbose: !!opts.verbose,
683
- redetect: !!opts.redetect,
684
- };
685
- const projectStatePath = join(process.cwd(), '.runwork', 'setup.json');
686
- const userStatePath = join(homedir(), '.runwork', 'setup.json');
687
- const projectState = loadSetupState(projectStatePath);
688
- const userState = loadSetupState(userStatePath);
689
- if (!projectState && !userState) {
690
- console.error('No setup state found. Run `runwork setup` first.');
691
- process.exit(1);
692
- }
693
- if (projectState) {
694
- await syncFromState(projectState, projectStatePath, credentials, syncOpts);
695
- }
696
- if (userState) {
697
- await syncFromState(userState, userStatePath, credentials, syncOpts);
698
- }
699
- if (!syncOpts.dryRun) {
700
- console.log('\nSync complete.');
701
- }
702
- });