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,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
- });