nomoreide 0.2.0 → 0.3.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 (624) hide show
  1. package/README.md +12 -9
  2. package/bin/nomoreide.js +82 -0
  3. package/package.json +24 -132
  4. package/dist/cli/agents.d.ts +0 -2
  5. package/dist/cli/agents.js +0 -43
  6. package/dist/cli/agents.js.map +0 -1
  7. package/dist/cli/commands.d.ts +0 -11
  8. package/dist/cli/commands.js +0 -235
  9. package/dist/cli/commands.js.map +0 -1
  10. package/dist/cli/daemon.d.ts +0 -15
  11. package/dist/cli/daemon.js +0 -139
  12. package/dist/cli/daemon.js.map +0 -1
  13. package/dist/cli/database.d.ts +0 -2
  14. package/dist/cli/database.js +0 -145
  15. package/dist/cli/database.js.map +0 -1
  16. package/dist/cli/errors.d.ts +0 -2
  17. package/dist/cli/errors.js +0 -3
  18. package/dist/cli/errors.js.map +0 -1
  19. package/dist/cli/flags.d.ts +0 -1
  20. package/dist/cli/flags.js +0 -19
  21. package/dist/cli/flags.js.map +0 -1
  22. package/dist/cli/git.d.ts +0 -2
  23. package/dist/cli/git.js +0 -113
  24. package/dist/cli/git.js.map +0 -1
  25. package/dist/cli/profile.d.ts +0 -2
  26. package/dist/cli/profile.js +0 -171
  27. package/dist/cli/profile.js.map +0 -1
  28. package/dist/core/agent-context.d.ts +0 -9
  29. package/dist/core/agent-context.js +0 -43
  30. package/dist/core/agent-context.js.map +0 -1
  31. package/dist/core/agent-env/antigravity-reader.d.ts +0 -7
  32. package/dist/core/agent-env/antigravity-reader.js +0 -86
  33. package/dist/core/agent-env/antigravity-reader.js.map +0 -1
  34. package/dist/core/agent-env/availability.d.ts +0 -6
  35. package/dist/core/agent-env/availability.js +0 -79
  36. package/dist/core/agent-env/availability.js.map +0 -1
  37. package/dist/core/agent-env/claude-reader.d.ts +0 -7
  38. package/dist/core/agent-env/claude-reader.js +0 -101
  39. package/dist/core/agent-env/claude-reader.js.map +0 -1
  40. package/dist/core/agent-env/codex-reader.d.ts +0 -11
  41. package/dist/core/agent-env/codex-reader.js +0 -164
  42. package/dist/core/agent-env/codex-reader.js.map +0 -1
  43. package/dist/core/agent-env/index.d.ts +0 -9
  44. package/dist/core/agent-env/index.js +0 -29
  45. package/dist/core/agent-env/index.js.map +0 -1
  46. package/dist/core/agent-env/managed-plugins.d.ts +0 -18
  47. package/dist/core/agent-env/managed-plugins.js +0 -68
  48. package/dist/core/agent-env/managed-plugins.js.map +0 -1
  49. package/dist/core/agent-env/plugin-reader.d.ts +0 -9
  50. package/dist/core/agent-env/plugin-reader.js +0 -174
  51. package/dist/core/agent-env/plugin-reader.js.map +0 -1
  52. package/dist/core/agent-env/shared.d.ts +0 -26
  53. package/dist/core/agent-env/shared.js +0 -116
  54. package/dist/core/agent-env/shared.js.map +0 -1
  55. package/dist/core/agent-env/types.d.ts +0 -66
  56. package/dist/core/agent-env/types.js +0 -7
  57. package/dist/core/agent-env/types.js.map +0 -1
  58. package/dist/core/agent-env-actions.d.ts +0 -117
  59. package/dist/core/agent-env-actions.js +0 -273
  60. package/dist/core/agent-env-actions.js.map +0 -1
  61. package/dist/core/agent-env-plugin-uninstall.d.ts +0 -11
  62. package/dist/core/agent-env-plugin-uninstall.js +0 -189
  63. package/dist/core/agent-env-plugin-uninstall.js.map +0 -1
  64. package/dist/core/agent-env-writers.d.ts +0 -71
  65. package/dist/core/agent-env-writers.js +0 -632
  66. package/dist/core/agent-env-writers.js.map +0 -1
  67. package/dist/core/agent-profiles/apply.d.ts +0 -57
  68. package/dist/core/agent-profiles/apply.js +0 -209
  69. package/dist/core/agent-profiles/apply.js.map +0 -1
  70. package/dist/core/agent-profiles/builtin.d.ts +0 -8
  71. package/dist/core/agent-profiles/builtin.js +0 -33
  72. package/dist/core/agent-profiles/builtin.js.map +0 -1
  73. package/dist/core/agent-profiles/credentials.d.ts +0 -26
  74. package/dist/core/agent-profiles/credentials.js +0 -151
  75. package/dist/core/agent-profiles/credentials.js.map +0 -1
  76. package/dist/core/agent-profiles/debug-setup.d.ts +0 -18
  77. package/dist/core/agent-profiles/debug-setup.js +0 -237
  78. package/dist/core/agent-profiles/debug-setup.js.map +0 -1
  79. package/dist/core/agent-profiles/index.d.ts +0 -18
  80. package/dist/core/agent-profiles/index.js +0 -19
  81. package/dist/core/agent-profiles/index.js.map +0 -1
  82. package/dist/core/agent-profiles/plugin-apply.d.ts +0 -16
  83. package/dist/core/agent-profiles/plugin-apply.js +0 -383
  84. package/dist/core/agent-profiles/plugin-apply.js.map +0 -1
  85. package/dist/core/agent-profiles/plugin-bundle.d.ts +0 -6
  86. package/dist/core/agent-profiles/plugin-bundle.js +0 -32
  87. package/dist/core/agent-profiles/plugin-bundle.js.map +0 -1
  88. package/dist/core/agent-profiles/publication.d.ts +0 -105
  89. package/dist/core/agent-profiles/publication.js +0 -126
  90. package/dist/core/agent-profiles/publication.js.map +0 -1
  91. package/dist/core/agent-profiles/registry-auth.d.ts +0 -25
  92. package/dist/core/agent-profiles/registry-auth.js +0 -78
  93. package/dist/core/agent-profiles/registry-auth.js.map +0 -1
  94. package/dist/core/agent-profiles/registry-client.d.ts +0 -98
  95. package/dist/core/agent-profiles/registry-client.js +0 -109
  96. package/dist/core/agent-profiles/registry-client.js.map +0 -1
  97. package/dist/core/agent-profiles/registry-config.d.ts +0 -62
  98. package/dist/core/agent-profiles/registry-config.js +0 -221
  99. package/dist/core/agent-profiles/registry-config.js.map +0 -1
  100. package/dist/core/agent-profiles/registry-transfer.d.ts +0 -42
  101. package/dist/core/agent-profiles/registry-transfer.js +0 -133
  102. package/dist/core/agent-profiles/registry-transfer.js.map +0 -1
  103. package/dist/core/agent-profiles/store.d.ts +0 -62
  104. package/dist/core/agent-profiles/store.js +0 -479
  105. package/dist/core/agent-profiles/store.js.map +0 -1
  106. package/dist/core/agent-profiles/transfer.d.ts +0 -27
  107. package/dist/core/agent-profiles/transfer.js +0 -359
  108. package/dist/core/agent-profiles/transfer.js.map +0 -1
  109. package/dist/core/agent-profiles/types.d.ts +0 -364
  110. package/dist/core/agent-profiles/types.js +0 -79
  111. package/dist/core/agent-profiles/types.js.map +0 -1
  112. package/dist/core/agent-runtime.d.ts +0 -114
  113. package/dist/core/agent-runtime.js +0 -494
  114. package/dist/core/agent-runtime.js.map +0 -1
  115. package/dist/core/agent-sessions.d.ts +0 -46
  116. package/dist/core/agent-sessions.js +0 -109
  117. package/dist/core/agent-sessions.js.map +0 -1
  118. package/dist/core/agent-settings.d.ts +0 -31
  119. package/dist/core/agent-settings.js +0 -129
  120. package/dist/core/agent-settings.js.map +0 -1
  121. package/dist/core/agent-terminal.d.ts +0 -22
  122. package/dist/core/agent-terminal.js +0 -62
  123. package/dist/core/agent-terminal.js.map +0 -1
  124. package/dist/core/agent-transcripts.d.ts +0 -29
  125. package/dist/core/agent-transcripts.js +0 -281
  126. package/dist/core/agent-transcripts.js.map +0 -1
  127. package/dist/core/app-settings.d.ts +0 -74
  128. package/dist/core/app-settings.js +0 -118
  129. package/dist/core/app-settings.js.map +0 -1
  130. package/dist/core/app-version.d.ts +0 -2
  131. package/dist/core/app-version.js +0 -16
  132. package/dist/core/app-version.js.map +0 -1
  133. package/dist/core/approval-broker.d.ts +0 -29
  134. package/dist/core/approval-broker.js +0 -48
  135. package/dist/core/approval-broker.js.map +0 -1
  136. package/dist/core/claude-settings.d.ts +0 -18
  137. package/dist/core/claude-settings.js +0 -48
  138. package/dist/core/claude-settings.js.map +0 -1
  139. package/dist/core/cloudflare-actions.d.ts +0 -90
  140. package/dist/core/cloudflare-actions.js +0 -178
  141. package/dist/core/cloudflare-actions.js.map +0 -1
  142. package/dist/core/cloudflare-auth.d.ts +0 -61
  143. package/dist/core/cloudflare-auth.js +0 -149
  144. package/dist/core/cloudflare-auth.js.map +0 -1
  145. package/dist/core/cloudflare-context.d.ts +0 -2
  146. package/dist/core/cloudflare-context.js +0 -106
  147. package/dist/core/cloudflare-context.js.map +0 -1
  148. package/dist/core/cloudflare-manager.d.ts +0 -258
  149. package/dist/core/cloudflare-manager.js +0 -414
  150. package/dist/core/cloudflare-manager.js.map +0 -1
  151. package/dist/core/cloudflare-provider.d.ts +0 -64
  152. package/dist/core/cloudflare-provider.js +0 -348
  153. package/dist/core/cloudflare-provider.js.map +0 -1
  154. package/dist/core/config-files.d.ts +0 -27
  155. package/dist/core/config-files.js +0 -154
  156. package/dist/core/config-files.js.map +0 -1
  157. package/dist/core/config-store.d.ts +0 -181
  158. package/dist/core/config-store.js +0 -1026
  159. package/dist/core/config-store.js.map +0 -1
  160. package/dist/core/context-library.d.ts +0 -53
  161. package/dist/core/context-library.js +0 -605
  162. package/dist/core/context-library.js.map +0 -1
  163. package/dist/core/context-types.d.ts +0 -83
  164. package/dist/core/context-types.js +0 -9
  165. package/dist/core/context-types.js.map +0 -1
  166. package/dist/core/daemon-client.d.ts +0 -84
  167. package/dist/core/daemon-client.js +0 -156
  168. package/dist/core/daemon-client.js.map +0 -1
  169. package/dist/core/daemon-lifecycle.d.ts +0 -59
  170. package/dist/core/daemon-lifecycle.js +0 -147
  171. package/dist/core/daemon-lifecycle.js.map +0 -1
  172. package/dist/core/db/catalog.d.ts +0 -57
  173. package/dist/core/db/catalog.js +0 -38
  174. package/dist/core/db/catalog.js.map +0 -1
  175. package/dist/core/db/data-masking.d.ts +0 -3
  176. package/dist/core/db/data-masking.js +0 -14
  177. package/dist/core/db/data-masking.js.map +0 -1
  178. package/dist/core/db/driver.d.ts +0 -151
  179. package/dist/core/db/driver.js +0 -209
  180. package/dist/core/db/driver.js.map +0 -1
  181. package/dist/core/db/export.d.ts +0 -17
  182. package/dist/core/db/export.js +0 -67
  183. package/dist/core/db/export.js.map +0 -1
  184. package/dist/core/db/mysql-driver.d.ts +0 -33
  185. package/dist/core/db/mysql-driver.js +0 -364
  186. package/dist/core/db/mysql-driver.js.map +0 -1
  187. package/dist/core/db/postgres-driver.d.ts +0 -34
  188. package/dist/core/db/postgres-driver.js +0 -430
  189. package/dist/core/db/postgres-driver.js.map +0 -1
  190. package/dist/core/db/sqlite-driver.d.ts +0 -30
  191. package/dist/core/db/sqlite-driver.js +0 -301
  192. package/dist/core/db/sqlite-driver.js.map +0 -1
  193. package/dist/core/db-peek.d.ts +0 -99
  194. package/dist/core/db-peek.js +0 -322
  195. package/dist/core/db-peek.js.map +0 -1
  196. package/dist/core/db-write.d.ts +0 -45
  197. package/dist/core/db-write.js +0 -190
  198. package/dist/core/db-write.js.map +0 -1
  199. package/dist/core/docker-inspect.d.ts +0 -34
  200. package/dist/core/docker-inspect.js +0 -108
  201. package/dist/core/docker-inspect.js.map +0 -1
  202. package/dist/core/docker-resources.d.ts +0 -28
  203. package/dist/core/docker-resources.js +0 -59
  204. package/dist/core/docker-resources.js.map +0 -1
  205. package/dist/core/docker-service-runner.d.ts +0 -21
  206. package/dist/core/docker-service-runner.js +0 -80
  207. package/dist/core/docker-service-runner.js.map +0 -1
  208. package/dist/core/docker-stats.d.ts +0 -24
  209. package/dist/core/docker-stats.js +0 -76
  210. package/dist/core/docker-stats.js.map +0 -1
  211. package/dist/core/docker.d.ts +0 -75
  212. package/dist/core/docker.js +0 -219
  213. package/dist/core/docker.js.map +0 -1
  214. package/dist/core/env-file.d.ts +0 -24
  215. package/dist/core/env-file.js +0 -123
  216. package/dist/core/env-file.js.map +0 -1
  217. package/dist/core/env-runtime.d.ts +0 -32
  218. package/dist/core/env-runtime.js +0 -42
  219. package/dist/core/env-runtime.js.map +0 -1
  220. package/dist/core/error-inbox.d.ts +0 -91
  221. package/dist/core/error-inbox.js +0 -292
  222. package/dist/core/error-inbox.js.map +0 -1
  223. package/dist/core/extensions.d.ts +0 -78
  224. package/dist/core/extensions.js +0 -41
  225. package/dist/core/extensions.js.map +0 -1
  226. package/dist/core/external-terminal.d.ts +0 -60
  227. package/dist/core/external-terminal.js +0 -429
  228. package/dist/core/external-terminal.js.map +0 -1
  229. package/dist/core/fix-loop.d.ts +0 -55
  230. package/dist/core/fix-loop.js +0 -73
  231. package/dist/core/fix-loop.js.map +0 -1
  232. package/dist/core/git-actions.d.ts +0 -69
  233. package/dist/core/git-actions.js +0 -161
  234. package/dist/core/git-actions.js.map +0 -1
  235. package/dist/core/git-graph-layout.d.ts +0 -34
  236. package/dist/core/git-graph-layout.js +0 -94
  237. package/dist/core/git-graph-layout.js.map +0 -1
  238. package/dist/core/git-identity.d.ts +0 -78
  239. package/dist/core/git-identity.js +0 -178
  240. package/dist/core/git-identity.js.map +0 -1
  241. package/dist/core/git-manager.d.ts +0 -129
  242. package/dist/core/git-manager.js +0 -509
  243. package/dist/core/git-manager.js.map +0 -1
  244. package/dist/core/git-worktrees.d.ts +0 -35
  245. package/dist/core/git-worktrees.js +0 -142
  246. package/dist/core/git-worktrees.js.map +0 -1
  247. package/dist/core/github-auth.d.ts +0 -28
  248. package/dist/core/github-auth.js +0 -134
  249. package/dist/core/github-auth.js.map +0 -1
  250. package/dist/core/github-context.d.ts +0 -12
  251. package/dist/core/github-context.js +0 -36
  252. package/dist/core/github-context.js.map +0 -1
  253. package/dist/core/github-manager.d.ts +0 -230
  254. package/dist/core/github-manager.js +0 -324
  255. package/dist/core/github-manager.js.map +0 -1
  256. package/dist/core/host-metrics.d.ts +0 -41
  257. package/dist/core/host-metrics.js +0 -93
  258. package/dist/core/host-metrics.js.map +0 -1
  259. package/dist/core/http-inspector.d.ts +0 -20
  260. package/dist/core/http-inspector.js +0 -106
  261. package/dist/core/http-inspector.js.map +0 -1
  262. package/dist/core/jetbrains-import.d.ts +0 -85
  263. package/dist/core/jetbrains-import.js +0 -599
  264. package/dist/core/jetbrains-import.js.map +0 -1
  265. package/dist/core/log-sources.d.ts +0 -21
  266. package/dist/core/log-sources.js +0 -219
  267. package/dist/core/log-sources.js.map +0 -1
  268. package/dist/core/log-store.d.ts +0 -33
  269. package/dist/core/log-store.js +0 -94
  270. package/dist/core/log-store.js.map +0 -1
  271. package/dist/core/log-volume.d.ts +0 -41
  272. package/dist/core/log-volume.js +0 -81
  273. package/dist/core/log-volume.js.map +0 -1
  274. package/dist/core/mcp-auth.d.ts +0 -27
  275. package/dist/core/mcp-auth.js +0 -90
  276. package/dist/core/mcp-auth.js.map +0 -1
  277. package/dist/core/metrics-store.d.ts +0 -74
  278. package/dist/core/metrics-store.js +0 -187
  279. package/dist/core/metrics-store.js.map +0 -1
  280. package/dist/core/one-time-skills.d.ts +0 -27
  281. package/dist/core/one-time-skills.js +0 -185
  282. package/dist/core/one-time-skills.js.map +0 -1
  283. package/dist/core/port-utils.d.ts +0 -23
  284. package/dist/core/port-utils.js +0 -83
  285. package/dist/core/port-utils.js.map +0 -1
  286. package/dist/core/process-manager.d.ts +0 -99
  287. package/dist/core/process-manager.js +0 -738
  288. package/dist/core/process-manager.js.map +0 -1
  289. package/dist/core/process-tree.d.ts +0 -17
  290. package/dist/core/process-tree.js +0 -64
  291. package/dist/core/process-tree.js.map +0 -1
  292. package/dist/core/project-overview.d.ts +0 -52
  293. package/dist/core/project-overview.js +0 -122
  294. package/dist/core/project-overview.js.map +0 -1
  295. package/dist/core/providers/api-base.d.ts +0 -24
  296. package/dist/core/providers/api-base.js +0 -44
  297. package/dist/core/providers/api-base.js.map +0 -1
  298. package/dist/core/providers/credentials.d.ts +0 -93
  299. package/dist/core/providers/credentials.js +0 -88
  300. package/dist/core/providers/credentials.js.map +0 -1
  301. package/dist/core/providers/deploy-provider.d.ts +0 -327
  302. package/dist/core/providers/deploy-provider.js +0 -25
  303. package/dist/core/providers/deploy-provider.js.map +0 -1
  304. package/dist/core/providers/egress.d.ts +0 -58
  305. package/dist/core/providers/egress.js +0 -124
  306. package/dist/core/providers/egress.js.map +0 -1
  307. package/dist/core/providers/host-bridge.d.ts +0 -20
  308. package/dist/core/providers/host-bridge.js +0 -57
  309. package/dist/core/providers/host-bridge.js.map +0 -1
  310. package/dist/core/providers/host-provider.d.ts +0 -160
  311. package/dist/core/providers/host-provider.js +0 -2
  312. package/dist/core/providers/host-provider.js.map +0 -1
  313. package/dist/core/providers/oauth.d.ts +0 -97
  314. package/dist/core/providers/oauth.js +0 -238
  315. package/dist/core/providers/oauth.js.map +0 -1
  316. package/dist/core/providers/project-resolution.d.ts +0 -81
  317. package/dist/core/providers/project-resolution.js +0 -101
  318. package/dist/core/providers/project-resolution.js.map +0 -1
  319. package/dist/core/providers/registry.d.ts +0 -73
  320. package/dist/core/providers/registry.js +0 -53
  321. package/dist/core/providers/registry.js.map +0 -1
  322. package/dist/core/providers/strings.d.ts +0 -95
  323. package/dist/core/providers/strings.js +0 -59
  324. package/dist/core/providers/strings.js.map +0 -1
  325. package/dist/core/public-config.d.ts +0 -18
  326. package/dist/core/public-config.js +0 -76
  327. package/dist/core/public-config.js.map +0 -1
  328. package/dist/core/read-only-files.d.ts +0 -28
  329. package/dist/core/read-only-files.js +0 -93
  330. package/dist/core/read-only-files.js.map +0 -1
  331. package/dist/core/repo-create.d.ts +0 -11
  332. package/dist/core/repo-create.js +0 -54
  333. package/dist/core/repo-create.js.map +0 -1
  334. package/dist/core/repo-match.d.ts +0 -12
  335. package/dist/core/repo-match.js +0 -40
  336. package/dist/core/repo-match.js.map +0 -1
  337. package/dist/core/repo-onboard.d.ts +0 -297
  338. package/dist/core/repo-onboard.js +0 -667
  339. package/dist/core/repo-onboard.js.map +0 -1
  340. package/dist/core/repro-bundle.d.ts +0 -30
  341. package/dist/core/repro-bundle.js +0 -116
  342. package/dist/core/repro-bundle.js.map +0 -1
  343. package/dist/core/service-graph.d.ts +0 -50
  344. package/dist/core/service-graph.js +0 -143
  345. package/dist/core/service-graph.js.map +0 -1
  346. package/dist/core/service-health.d.ts +0 -10
  347. package/dist/core/service-health.js +0 -46
  348. package/dist/core/service-health.js.map +0 -1
  349. package/dist/core/service-log-source.d.ts +0 -9
  350. package/dist/core/service-log-source.js +0 -49
  351. package/dist/core/service-log-source.js.map +0 -1
  352. package/dist/core/service-registry.d.ts +0 -52
  353. package/dist/core/service-registry.js +0 -101
  354. package/dist/core/service-registry.js.map +0 -1
  355. package/dist/core/snapshot-manager.d.ts +0 -62
  356. package/dist/core/snapshot-manager.js +0 -219
  357. package/dist/core/snapshot-manager.js.map +0 -1
  358. package/dist/core/ssh-servers.d.ts +0 -89
  359. package/dist/core/ssh-servers.js +0 -251
  360. package/dist/core/ssh-servers.js.map +0 -1
  361. package/dist/core/ssh-service-runner.d.ts +0 -7
  362. package/dist/core/ssh-service-runner.js +0 -36
  363. package/dist/core/ssh-service-runner.js.map +0 -1
  364. package/dist/core/ssh-setup.d.ts +0 -11
  365. package/dist/core/ssh-setup.js +0 -49
  366. package/dist/core/ssh-setup.js.map +0 -1
  367. package/dist/core/system-processes.d.ts +0 -29
  368. package/dist/core/system-processes.js +0 -119
  369. package/dist/core/system-processes.js.map +0 -1
  370. package/dist/core/terminal-manager.d.ts +0 -123
  371. package/dist/core/terminal-manager.js +0 -470
  372. package/dist/core/terminal-manager.js.map +0 -1
  373. package/dist/core/terminal-session.d.ts +0 -122
  374. package/dist/core/terminal-session.js +0 -242
  375. package/dist/core/terminal-session.js.map +0 -1
  376. package/dist/core/terminal-spawn.d.ts +0 -26
  377. package/dist/core/terminal-spawn.js +0 -63
  378. package/dist/core/terminal-spawn.js.map +0 -1
  379. package/dist/core/test-runner.d.ts +0 -69
  380. package/dist/core/test-runner.js +0 -199
  381. package/dist/core/test-runner.js.map +0 -1
  382. package/dist/core/timeline-store.d.ts +0 -20
  383. package/dist/core/timeline-store.js +0 -36
  384. package/dist/core/timeline-store.js.map +0 -1
  385. package/dist/core/tool-call-store.d.ts +0 -25
  386. package/dist/core/tool-call-store.js +0 -62
  387. package/dist/core/tool-call-store.js.map +0 -1
  388. package/dist/core/types.d.ts +0 -312
  389. package/dist/core/types.js +0 -2
  390. package/dist/core/types.js.map +0 -1
  391. package/dist/core/usage-history.d.ts +0 -81
  392. package/dist/core/usage-history.js +0 -149
  393. package/dist/core/usage-history.js.map +0 -1
  394. package/dist/core/vercel-actions.d.ts +0 -71
  395. package/dist/core/vercel-actions.js +0 -109
  396. package/dist/core/vercel-actions.js.map +0 -1
  397. package/dist/core/vercel-auth.d.ts +0 -40
  398. package/dist/core/vercel-auth.js +0 -88
  399. package/dist/core/vercel-auth.js.map +0 -1
  400. package/dist/core/vercel-context.d.ts +0 -2
  401. package/dist/core/vercel-context.js +0 -97
  402. package/dist/core/vercel-context.js.map +0 -1
  403. package/dist/core/vercel-manager.d.ts +0 -268
  404. package/dist/core/vercel-manager.js +0 -401
  405. package/dist/core/vercel-manager.js.map +0 -1
  406. package/dist/core/vercel-oauth.d.ts +0 -37
  407. package/dist/core/vercel-oauth.js +0 -57
  408. package/dist/core/vercel-oauth.js.map +0 -1
  409. package/dist/core/vercel-provider.d.ts +0 -23
  410. package/dist/core/vercel-provider.js +0 -276
  411. package/dist/core/vercel-provider.js.map +0 -1
  412. package/dist/core/vultr-actions.d.ts +0 -52
  413. package/dist/core/vultr-actions.js +0 -62
  414. package/dist/core/vultr-actions.js.map +0 -1
  415. package/dist/core/vultr-auth.d.ts +0 -32
  416. package/dist/core/vultr-auth.js +0 -54
  417. package/dist/core/vultr-auth.js.map +0 -1
  418. package/dist/core/vultr-context.d.ts +0 -2
  419. package/dist/core/vultr-context.js +0 -55
  420. package/dist/core/vultr-context.js.map +0 -1
  421. package/dist/core/vultr-manager.d.ts +0 -113
  422. package/dist/core/vultr-manager.js +0 -170
  423. package/dist/core/vultr-manager.js.map +0 -1
  424. package/dist/core/vultr-provider.d.ts +0 -69
  425. package/dist/core/vultr-provider.js +0 -226
  426. package/dist/core/vultr-provider.js.map +0 -1
  427. package/dist/core/workflow-triggers.d.ts +0 -139
  428. package/dist/core/workflow-triggers.js +0 -208
  429. package/dist/core/workflow-triggers.js.map +0 -1
  430. package/dist/core/workflows.d.ts +0 -290
  431. package/dist/core/workflows.js +0 -190
  432. package/dist/core/workflows.js.map +0 -1
  433. package/dist/index.d.ts +0 -2
  434. package/dist/index.js +0 -66
  435. package/dist/index.js.map +0 -1
  436. package/dist/mcp/server.d.ts +0 -37
  437. package/dist/mcp/server.js +0 -84
  438. package/dist/mcp/server.js.map +0 -1
  439. package/dist/mcp/tools/agent-env.d.ts +0 -9
  440. package/dist/mcp/tools/agent-env.js +0 -160
  441. package/dist/mcp/tools/agent-env.js.map +0 -1
  442. package/dist/mcp/tools/agent-profiles.d.ts +0 -9
  443. package/dist/mcp/tools/agent-profiles.js +0 -197
  444. package/dist/mcp/tools/agent-profiles.js.map +0 -1
  445. package/dist/mcp/tools/agent-registry.d.ts +0 -9
  446. package/dist/mcp/tools/agent-registry.js +0 -81
  447. package/dist/mcp/tools/agent-registry.js.map +0 -1
  448. package/dist/mcp/tools/agent.d.ts +0 -4
  449. package/dist/mcp/tools/agent.js +0 -29
  450. package/dist/mcp/tools/agent.js.map +0 -1
  451. package/dist/mcp/tools/context.d.ts +0 -36
  452. package/dist/mcp/tools/context.js +0 -69
  453. package/dist/mcp/tools/context.js.map +0 -1
  454. package/dist/mcp/tools/database.d.ts +0 -9
  455. package/dist/mcp/tools/database.js +0 -166
  456. package/dist/mcp/tools/database.js.map +0 -1
  457. package/dist/mcp/tools/docs.d.ts +0 -29
  458. package/dist/mcp/tools/docs.js +0 -134
  459. package/dist/mcp/tools/docs.js.map +0 -1
  460. package/dist/mcp/tools/errors.d.ts +0 -12
  461. package/dist/mcp/tools/errors.js +0 -47
  462. package/dist/mcp/tools/errors.js.map +0 -1
  463. package/dist/mcp/tools/git.d.ts +0 -4
  464. package/dist/mcp/tools/git.js +0 -209
  465. package/dist/mcp/tools/git.js.map +0 -1
  466. package/dist/mcp/tools/github.d.ts +0 -4
  467. package/dist/mcp/tools/github.js +0 -196
  468. package/dist/mcp/tools/github.js.map +0 -1
  469. package/dist/mcp/tools/index.d.ts +0 -36
  470. package/dist/mcp/tools/index.js +0 -61
  471. package/dist/mcp/tools/index.js.map +0 -1
  472. package/dist/mcp/tools/onboard.d.ts +0 -10
  473. package/dist/mcp/tools/onboard.js +0 -30
  474. package/dist/mcp/tools/onboard.js.map +0 -1
  475. package/dist/mcp/tools/provider.d.ts +0 -16
  476. package/dist/mcp/tools/provider.js +0 -110
  477. package/dist/mcp/tools/provider.js.map +0 -1
  478. package/dist/mcp/tools/services.d.ts +0 -13
  479. package/dist/mcp/tools/services.js +0 -204
  480. package/dist/mcp/tools/services.js.map +0 -1
  481. package/dist/mcp/tools/snapshots.d.ts +0 -8
  482. package/dist/mcp/tools/snapshots.js +0 -37
  483. package/dist/mcp/tools/snapshots.js.map +0 -1
  484. package/dist/mcp/tools/terminal.d.ts +0 -4
  485. package/dist/mcp/tools/terminal.js +0 -38
  486. package/dist/mcp/tools/terminal.js.map +0 -1
  487. package/dist/tui/app.d.ts +0 -22
  488. package/dist/tui/app.js +0 -138
  489. package/dist/tui/app.js.map +0 -1
  490. package/dist/web/agent-info.d.ts +0 -82
  491. package/dist/web/agent-info.js +0 -775
  492. package/dist/web/agent-info.js.map +0 -1
  493. package/dist/web/client/assets/SymbolsNerdFontMono-Regular-DDncdh2F.ttf +0 -0
  494. package/dist/web/client/assets/code-editor-TE0sjFGO.js +0 -30
  495. package/dist/web/client/assets/context-graph-B9MnBpp6.js +0 -7
  496. package/dist/web/client/assets/core-DhEqZVGG.js +0 -1
  497. package/dist/web/client/assets/event-BK_86lmQ.js +0 -1
  498. package/dist/web/client/assets/index-BhDAhmA1.js +0 -1
  499. package/dist/web/client/assets/index-CSo__8A6.css +0 -1
  500. package/dist/web/client/assets/index-DAJvBqn9.js +0 -352
  501. package/dist/web/client/assets/nomoreide-favicon-Ds7Tgj9p.svg +0 -24
  502. package/dist/web/client/assets/system-process-table-DetWu0Gj.js +0 -1
  503. package/dist/web/client/assets/window-DlR023_X.js +0 -1
  504. package/dist/web/client/index.html +0 -44
  505. package/dist/web/dashboard.d.ts +0 -61
  506. package/dist/web/dashboard.js +0 -221
  507. package/dist/web/dashboard.js.map +0 -1
  508. package/dist/web/directories.d.ts +0 -27
  509. package/dist/web/directories.js +0 -81
  510. package/dist/web/directories.js.map +0 -1
  511. package/dist/web/http-utils.d.ts +0 -13
  512. package/dist/web/http-utils.js +0 -72
  513. package/dist/web/http-utils.js.map +0 -1
  514. package/dist/web/routes/agent-chat-routes.d.ts +0 -3
  515. package/dist/web/routes/agent-chat-routes.js +0 -186
  516. package/dist/web/routes/agent-chat-routes.js.map +0 -1
  517. package/dist/web/routes/agent-env-routes.d.ts +0 -9
  518. package/dist/web/routes/agent-env-routes.js +0 -86
  519. package/dist/web/routes/agent-env-routes.js.map +0 -1
  520. package/dist/web/routes/agent-profile-routes.d.ts +0 -8
  521. package/dist/web/routes/agent-profile-routes.js +0 -211
  522. package/dist/web/routes/agent-profile-routes.js.map +0 -1
  523. package/dist/web/routes/agent-registry-routes.d.ts +0 -2
  524. package/dist/web/routes/agent-registry-routes.js +0 -375
  525. package/dist/web/routes/agent-registry-routes.js.map +0 -1
  526. package/dist/web/routes/agent-routes.d.ts +0 -3
  527. package/dist/web/routes/agent-routes.js +0 -73
  528. package/dist/web/routes/agent-routes.js.map +0 -1
  529. package/dist/web/routes/agent-settings-routes.d.ts +0 -8
  530. package/dist/web/routes/agent-settings-routes.js +0 -67
  531. package/dist/web/routes/agent-settings-routes.js.map +0 -1
  532. package/dist/web/routes/context-library-routes.d.ts +0 -2
  533. package/dist/web/routes/context-library-routes.js +0 -139
  534. package/dist/web/routes/context-library-routes.js.map +0 -1
  535. package/dist/web/routes/context.d.ts +0 -73
  536. package/dist/web/routes/context.js +0 -48
  537. package/dist/web/routes/context.js.map +0 -1
  538. package/dist/web/routes/dashboard-routes.d.ts +0 -3
  539. package/dist/web/routes/dashboard-routes.js +0 -47
  540. package/dist/web/routes/dashboard-routes.js.map +0 -1
  541. package/dist/web/routes/database-routes.d.ts +0 -3
  542. package/dist/web/routes/database-routes.js +0 -341
  543. package/dist/web/routes/database-routes.js.map +0 -1
  544. package/dist/web/routes/docker-routes.d.ts +0 -7
  545. package/dist/web/routes/docker-routes.js +0 -122
  546. package/dist/web/routes/docker-routes.js.map +0 -1
  547. package/dist/web/routes/errors-routes.d.ts +0 -3
  548. package/dist/web/routes/errors-routes.js +0 -77
  549. package/dist/web/routes/errors-routes.js.map +0 -1
  550. package/dist/web/routes/extensions-routes.d.ts +0 -14
  551. package/dist/web/routes/extensions-routes.js +0 -21
  552. package/dist/web/routes/extensions-routes.js.map +0 -1
  553. package/dist/web/routes/git-routes.d.ts +0 -3
  554. package/dist/web/routes/git-routes.js +0 -598
  555. package/dist/web/routes/git-routes.js.map +0 -1
  556. package/dist/web/routes/github-context.d.ts +0 -11
  557. package/dist/web/routes/github-context.js +0 -34
  558. package/dist/web/routes/github-context.js.map +0 -1
  559. package/dist/web/routes/github-routes.d.ts +0 -2
  560. package/dist/web/routes/github-routes.js +0 -699
  561. package/dist/web/routes/github-routes.js.map +0 -1
  562. package/dist/web/routes/host-routes.d.ts +0 -2
  563. package/dist/web/routes/host-routes.js +0 -188
  564. package/dist/web/routes/host-routes.js.map +0 -1
  565. package/dist/web/routes/index.d.ts +0 -10
  566. package/dist/web/routes/index.js +0 -72
  567. package/dist/web/routes/index.js.map +0 -1
  568. package/dist/web/routes/jetbrains-import-routes.d.ts +0 -2
  569. package/dist/web/routes/jetbrains-import-routes.js +0 -121
  570. package/dist/web/routes/jetbrains-import-routes.js.map +0 -1
  571. package/dist/web/routes/log-sources-routes.d.ts +0 -6
  572. package/dist/web/routes/log-sources-routes.js +0 -102
  573. package/dist/web/routes/log-sources-routes.js.map +0 -1
  574. package/dist/web/routes/metrics-routes.d.ts +0 -3
  575. package/dist/web/routes/metrics-routes.js +0 -60
  576. package/dist/web/routes/metrics-routes.js.map +0 -1
  577. package/dist/web/routes/onboard-routes.d.ts +0 -9
  578. package/dist/web/routes/onboard-routes.js +0 -146
  579. package/dist/web/routes/onboard-routes.js.map +0 -1
  580. package/dist/web/routes/overview-routes.d.ts +0 -2
  581. package/dist/web/routes/overview-routes.js +0 -36
  582. package/dist/web/routes/overview-routes.js.map +0 -1
  583. package/dist/web/routes/provider-routes.d.ts +0 -2
  584. package/dist/web/routes/provider-routes.js +0 -558
  585. package/dist/web/routes/provider-routes.js.map +0 -1
  586. package/dist/web/routes/service-routes.d.ts +0 -3
  587. package/dist/web/routes/service-routes.js +0 -511
  588. package/dist/web/routes/service-routes.js.map +0 -1
  589. package/dist/web/routes/settings-routes.d.ts +0 -2
  590. package/dist/web/routes/settings-routes.js +0 -151
  591. package/dist/web/routes/settings-routes.js.map +0 -1
  592. package/dist/web/routes/shell-routes.d.ts +0 -22
  593. package/dist/web/routes/shell-routes.js +0 -75
  594. package/dist/web/routes/shell-routes.js.map +0 -1
  595. package/dist/web/routes/skills-routes.d.ts +0 -2
  596. package/dist/web/routes/skills-routes.js +0 -49
  597. package/dist/web/routes/skills-routes.js.map +0 -1
  598. package/dist/web/routes/snapshot-routes.d.ts +0 -8
  599. package/dist/web/routes/snapshot-routes.js +0 -194
  600. package/dist/web/routes/snapshot-routes.js.map +0 -1
  601. package/dist/web/routes/ssh-server-routes.d.ts +0 -10
  602. package/dist/web/routes/ssh-server-routes.js +0 -163
  603. package/dist/web/routes/ssh-server-routes.js.map +0 -1
  604. package/dist/web/routes/terminal-routes.d.ts +0 -7
  605. package/dist/web/routes/terminal-routes.js +0 -313
  606. package/dist/web/routes/terminal-routes.js.map +0 -1
  607. package/dist/web/routes/workflow-routes.d.ts +0 -8
  608. package/dist/web/routes/workflow-routes.js +0 -45
  609. package/dist/web/routes/workflow-routes.js.map +0 -1
  610. package/dist/web/routes/workflow-trigger-routes.d.ts +0 -9
  611. package/dist/web/routes/workflow-trigger-routes.js +0 -78
  612. package/dist/web/routes/workflow-trigger-routes.js.map +0 -1
  613. package/dist/web/server.d.ts +0 -31
  614. package/dist/web/server.js +0 -325
  615. package/dist/web/server.js.map +0 -1
  616. package/dist/web/service-tester.d.ts +0 -16
  617. package/dist/web/service-tester.js +0 -107
  618. package/dist/web/service-tester.js.map +0 -1
  619. package/dist/web/static-assets.d.ts +0 -9
  620. package/dist/web/static-assets.js +0 -77
  621. package/dist/web/static-assets.js.map +0 -1
  622. package/dist/web/usage-info.d.ts +0 -56
  623. package/dist/web/usage-info.js +0 -265
  624. package/dist/web/usage-info.js.map +0 -1
@@ -1,1026 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { execFile } from "node:child_process";
3
- import { mkdir, open, realpath, readFile, rename, stat, unlink, writeFile, } from "node:fs/promises";
4
- import { homedir } from "node:os";
5
- import { basename, dirname, isAbsolute, join } from "node:path";
6
- import { promisify } from "node:util";
7
- import { z } from "zod";
8
- import { workflowSchema } from "./workflows.js";
9
- import { workflowTriggerSchema } from "./workflow-triggers.js";
10
- import { GitWorktreeManager } from "./git-worktrees.js";
11
- const execFileAsync = promisify(execFile);
12
- const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
13
- const CONFIG_LOCK_WAIT_MS = 5_000;
14
- const CONFIG_LOCK_STALE_MS = 30_000;
15
- const CONFIG_LOCK_RETRY_MIN_MS = 10;
16
- const CONFIG_LOCK_RETRY_MAX_MS = 50;
17
- const baseServiceSchema = z.object({
18
- name: z.string().min(1),
19
- port: z.number().int().positive().max(65535).optional(),
20
- description: z.string().optional(),
21
- /** Command used by the Test Runner; defaults to `npm test` when absent. */
22
- test: z.string().min(1).optional(),
23
- /** Services that must be running/healthy before this one (bundle start order). */
24
- dependsOn: z.array(z.string().min(1)).optional(),
25
- /**
26
- * Explicit project assignment, overriding the cwd-containment inference.
27
- * Needed because a remote service's `cwd` is a path on another machine
28
- * (`/var/www/...`, `/root`) and can never sit under a local repo root, so
29
- * inference alone leaves those services in no project at all.
30
- */
31
- projectPath: z.string().min(1).optional(),
32
- });
33
- const serviceEnvSchema = z
34
- .record(z.string())
35
- .refine((env) => Object.keys(env).every((key) => ENV_KEY_PATTERN.test(key)), {
36
- message: "Environment variable names must use letters, numbers, and underscores.",
37
- });
38
- const localServiceSchema = baseServiceSchema.extend({
39
- kind: z.literal("local").optional(),
40
- command: z.string().min(1),
41
- args: z.array(z.string().refine((value) => !value.includes("\0"))).optional(),
42
- cwd: z.string().min(1),
43
- env: serviceEnvSchema.optional(),
44
- });
45
- const dockerServiceSchema = baseServiceSchema.extend({
46
- kind: z.literal("docker-compose"),
47
- cwd: z.string().min(1),
48
- composeFile: z.string().min(1).optional(),
49
- composeService: z.string().min(1),
50
- });
51
- const sshServiceSchema = baseServiceSchema.extend({
52
- kind: z.literal("ssh"),
53
- host: z.string().min(1),
54
- cwd: z.string().min(1),
55
- command: z
56
- .string()
57
- .min(1)
58
- .refine((value) => !value.includes("\0"), {
59
- message: "SSH command contains invalid null byte.",
60
- }),
61
- env: serviceEnvSchema.optional(),
62
- });
63
- const serviceSchema = z.union([
64
- localServiceSchema,
65
- dockerServiceSchema,
66
- sshServiceSchema,
67
- ]);
68
- const bundleSchema = z.object({
69
- name: z.string().min(1),
70
- services: z.array(z.string().min(1)),
71
- });
72
- const githubCredentialSchema = z.discriminatedUnion("source", [
73
- z.object({
74
- source: z.literal("gh"),
75
- host: z.string().min(1),
76
- login: z.string().min(1),
77
- }),
78
- z.object({
79
- source: z.literal("stored"),
80
- host: z.string().min(1),
81
- }),
82
- ]);
83
- const gitRepositorySchema = z.object({
84
- name: z.string().min(1),
85
- path: z.string().min(1),
86
- activeWorktreePath: z.string().min(1).optional(),
87
- githubCredential: githubCredentialSchema.optional(),
88
- /** Pinned deploy-provider project per provider id; see `providerProjects`. */
89
- providerProjects: z.record(z.string(), z.string().min(1)).optional(),
90
- });
91
- /** Upper bound on board-pinned repos, mirroring the web UI's 5-column cap. */
92
- const MAX_BOARD_REPOSITORIES = 5;
93
- const databaseSchema = z.object({
94
- name: z.string().min(1),
95
- engine: z.enum(["postgres", "mysql", "sqlite"]),
96
- url: z.string().min(1),
97
- writeUnlocked: z.boolean().optional(),
98
- projectPath: z.string().min(1).optional(),
99
- });
100
- const logSourceSchema = z
101
- .object({
102
- name: z.string().min(1),
103
- kind: z.enum(["file", "ssh", "command"]),
104
- path: z.string().min(1).optional(),
105
- host: z.string().min(1).optional(),
106
- command: z.string().min(1).optional(),
107
- cwd: z.string().min(1).optional(),
108
- driver: z.enum(["journald", "docker"]).optional(),
109
- unit: z.string().min(1).optional(),
110
- container: z.string().min(1).optional(),
111
- })
112
- .superRefine((source, ctx) => {
113
- if (source.driver === "journald") {
114
- if (!source.unit) {
115
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "journald log source requires a unit." });
116
- }
117
- return; // driver sources build their own query; kind-based paths don't apply.
118
- }
119
- if (source.driver === "docker") {
120
- if (!source.container) {
121
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "docker log source requires a container." });
122
- }
123
- return;
124
- }
125
- if (source.kind === "file" && !source.path) {
126
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "File log source requires a path." });
127
- }
128
- if (source.kind === "ssh" && (!source.host || !source.path)) {
129
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "SSH log source requires host and path." });
130
- }
131
- if (source.kind === "command" && !source.command) {
132
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Command log source requires a command." });
133
- }
134
- });
135
- const sshHostPattern = /^[A-Za-z0-9][A-Za-z0-9._:@-]*$/;
136
- const sshServerSchema = z.object({
137
- host: z
138
- .string()
139
- .trim()
140
- .min(1)
141
- .max(255)
142
- .regex(sshHostPattern, "SSH host must be a host name or ~/.ssh/config alias."),
143
- name: z.string().trim().min(1).max(80).optional(),
144
- environment: z.string().trim().min(1).max(40).optional(),
145
- });
146
- const githubTokenSchema = z.object({
147
- host: z.string().min(1),
148
- token: z.string().min(1),
149
- /**
150
- * Who the token belongs to, captured once at connect time. Optional because
151
- * tokens stored before this existed stay valid — the GitHub status route
152
- * backfills them on the next check.
153
- */
154
- login: z.string().min(1).optional(),
155
- avatarUrl: z.string().url().optional(),
156
- });
157
- /**
158
- * Commit identity for a GitHub account, cached so committing does not spend an
159
- * API call resolving a name and address that effectively never change.
160
- */
161
- const githubIdentitySchema = z.object({
162
- host: z.string().min(1),
163
- login: z.string().min(1),
164
- name: z.string().min(1),
165
- email: z.string().min(1),
166
- });
167
- /**
168
- * A provider connection. A `cli` connection stores no token — it is re-read
169
- * from the vendor CLI's auth file per request — so `token` is set only for
170
- * `stored` (the pasted token) and `oauth` (the current access token, alongside
171
- * the refresh token that renews it).
172
- */
173
- const providerConnectionSchema = z.object({
174
- source: z.enum(["cli", "stored", "oauth"]),
175
- token: z.string().min(1).optional(),
176
- refreshToken: z.string().min(1).optional(),
177
- expiresAt: z.number().int().positive().optional(),
178
- clientId: z.string().min(1).optional(),
179
- scopeId: z.string().min(1).optional(),
180
- scopeSlug: z.string().min(1).optional(),
181
- username: z.string().min(1).optional(),
182
- });
183
- /** Provider ids key `connections` and `providerProjects`; keep them file-safe. */
184
- const providerIdSchema = z.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, {
185
- message: "a provider id must be lowercase alphanumeric or dashes",
186
- });
187
- /**
188
- * Display name for a provider id in user-facing errors. ConfigStore has no
189
- * access to provider manifests, so it title-cases the id — which is exactly
190
- * right for `vercel`, `cloudflare`, and `vultr`. A provider whose name needs
191
- * more than that should surface its own message at the route layer.
192
- */
193
- function providerLabel(providerId) {
194
- return providerId.charAt(0).toUpperCase() + providerId.slice(1);
195
- }
196
- export const projectPreferencesSchema = z
197
- .object({
198
- logs: z
199
- .object({
200
- showTimestamps: z.boolean(),
201
- wrapLines: z.boolean(),
202
- })
203
- .strict(),
204
- database: z
205
- .object({
206
- confirmWrites: z.boolean(),
207
- resultLimit: z.number().int().min(10).max(5_000),
208
- })
209
- .strict(),
210
- })
211
- .strict();
212
- export const projectPreferencesPatchSchema = z
213
- .object({
214
- logs: z
215
- .object({
216
- showTimestamps: z.boolean().optional(),
217
- wrapLines: z.boolean().optional(),
218
- })
219
- .strict()
220
- .optional(),
221
- database: z
222
- .object({
223
- confirmWrites: z.boolean().optional(),
224
- resultLimit: z.number().int().min(10).max(5_000).optional(),
225
- })
226
- .strict()
227
- .optional(),
228
- })
229
- .strict();
230
- export const DEFAULT_PROJECT_PREFERENCES = Object.freeze({
231
- logs: Object.freeze({ showTimestamps: true, wrapLines: true }),
232
- database: Object.freeze({ confirmWrites: true, resultLimit: 100 }),
233
- });
234
- /**
235
- * Provider identity as it was stored before connections were keyed by provider.
236
- * Both legacy shapes below are Vercel's, because it was the only provider.
237
- */
238
- const LEGACY_PROVIDER_ID = "vercel";
239
- /**
240
- * Lift the pre-registry Vercel fields into their provider-keyed homes:
241
- *
242
- * config.vercel → config.connections.vercel
243
- * connection.teamId / .teamSlug → .scopeId / .scopeSlug
244
- * repository.vercelProjectId → repository.providerProjects.vercel
245
- *
246
- * Runs as a parse-time preprocess rather than a one-shot upgrade script so that
247
- * a config written by an older build is readable on every load, not just the
248
- * first one after upgrading. `configSchema` is non-strict, so the legacy keys
249
- * are dropped on the next write with no further action.
250
- *
251
- * Existing provider-keyed values win: if both shapes are somehow present, the
252
- * new one is authoritative and the legacy key is simply discarded.
253
- */
254
- function migrateLegacyProviderFields(input) {
255
- if (!isRecord(input))
256
- return input;
257
- const config = { ...input };
258
- const legacy = config[LEGACY_PROVIDER_ID];
259
- if (isRecord(legacy)) {
260
- const { teamId, teamSlug, ...rest } = legacy;
261
- const existing = isRecord(config.connections) ? config.connections : {};
262
- config.connections = {
263
- [LEGACY_PROVIDER_ID]: {
264
- ...rest,
265
- ...(teamId === undefined ? {} : { scopeId: teamId }),
266
- ...(teamSlug === undefined ? {} : { scopeSlug: teamSlug }),
267
- },
268
- ...existing,
269
- };
270
- }
271
- if (Array.isArray(config.gitRepositories)) {
272
- config.gitRepositories = config.gitRepositories.map((entry) => {
273
- if (!isRecord(entry) || entry.vercelProjectId === undefined)
274
- return entry;
275
- const { vercelProjectId, ...rest } = entry;
276
- const existing = isRecord(entry.providerProjects) ? entry.providerProjects : {};
277
- return {
278
- ...rest,
279
- providerProjects: { [LEGACY_PROVIDER_ID]: vercelProjectId, ...existing },
280
- };
281
- });
282
- }
283
- return config;
284
- }
285
- function isRecord(value) {
286
- return typeof value === "object" && value !== null && !Array.isArray(value);
287
- }
288
- const configShape = z.object({
289
- version: z.literal(1),
290
- services: z.array(serviceSchema),
291
- bundles: z.array(bundleSchema),
292
- gitRepositories: z.array(gitRepositorySchema).default([]),
293
- selectedGitRepository: z.string().min(1).optional(),
294
- /**
295
- * Ordered names of repositories pinned to the multi-repo board. Undefined
296
- * means "never curated" → the board shows every registered repo; an empty
297
- * array means the user has explicitly cleared the board.
298
- */
299
- gitBoardRepositories: z.array(z.string().min(1)).optional(),
300
- databases: z.array(databaseSchema).default([]),
301
- logSources: z.array(logSourceSchema).default([]),
302
- sshServers: z.array(sshServerSchema).default([]),
303
- githubTokens: z.array(githubTokenSchema).default([]),
304
- githubIdentities: z.array(githubIdentitySchema).default([]),
305
- /**
306
- * How each provider authenticates, keyed by provider id. A missing entry
307
- * means that provider is not connected.
308
- */
309
- connections: z.record(providerIdSchema, providerConnectionSchema).default({}),
310
- workflows: z.array(workflowSchema).default([]),
311
- /** Event→workflow bindings that auto-fire workflows (IDEAS #16). */
312
- workflowTriggers: z.array(workflowTriggerSchema).default([]),
313
- /**
314
- * Which CLI the in-dock agent chat drives. Undefined = "never chosen" → fall
315
- * back to startup-agent detection. Set explicitly when the user picks/switches
316
- * providers, so the choice sticks across CLI/web/desktop.
317
- */
318
- chatProvider: z.enum(["claude", "codex"]).optional(),
319
- /**
320
- * Model each agent CLI is pinned to, keyed by provider. A missing entry means
321
- * "let the CLI pick", which is why this is a partial map rather than a pair of
322
- * defaulted fields — there is no model name that safely stands in for "the
323
- * provider's own default".
324
- */
325
- chatModels: z
326
- .object({
327
- claude: z.string().trim().min(1).max(64).optional(),
328
- codex: z.string().trim().min(1).max(64).optional(),
329
- })
330
- .optional(),
331
- preferences: projectPreferencesSchema.optional(),
332
- });
333
- const configSchema = z.preprocess(migrateLegacyProviderFields, configShape);
334
- const defaultConfig = {
335
- version: 1,
336
- services: [],
337
- bundles: [],
338
- gitRepositories: [],
339
- databases: [],
340
- logSources: [],
341
- sshServers: [],
342
- githubTokens: [],
343
- githubIdentities: [],
344
- connections: {},
345
- workflows: [],
346
- workflowTriggers: [],
347
- };
348
- export function defaultGlobalConfigPath() {
349
- const base = process.env.XDG_CONFIG_HOME?.trim();
350
- const root = base && base.length > 0 ? base : join(homedir(), ".config");
351
- return join(root, "nomoreide", "config.json");
352
- }
353
- export class ConfigStore {
354
- configPath;
355
- mutationQueue = Promise.resolve();
356
- constructor(configPath = defaultGlobalConfigPath()) {
357
- this.configPath = configPath;
358
- }
359
- async load() {
360
- return this.loadUnlocked();
361
- }
362
- async loadUnlocked() {
363
- try {
364
- const raw = await readFile(this.configPath, "utf8");
365
- return configSchema.parse(JSON.parse(raw));
366
- }
367
- catch (error) {
368
- if (isMissingFileError(error)) {
369
- return structuredClone(defaultConfig);
370
- }
371
- throw error;
372
- }
373
- }
374
- async save(config) {
375
- await this.enqueueMutation(() => this.withConfigLock(() => this.persistUnlocked(config)));
376
- }
377
- async persistUnlocked(config) {
378
- const parsed = configSchema.parse(config);
379
- const parentDirectory = dirname(this.configPath);
380
- const temporaryPath = join(parentDirectory, `.${basename(this.configPath)}.${process.pid}.${randomUUID()}.tmp`);
381
- await mkdir(parentDirectory, { recursive: true });
382
- try {
383
- await writeFile(temporaryPath, `${JSON.stringify(parsed, null, 2)}\n`, { flag: "wx", mode: 0o600 });
384
- await rename(temporaryPath, this.configPath);
385
- }
386
- catch (error) {
387
- await unlink(temporaryPath).catch(() => undefined);
388
- throw error;
389
- }
390
- }
391
- async getPreferences() {
392
- const config = await this.load();
393
- return structuredClone(config.preferences ?? DEFAULT_PROJECT_PREFERENCES);
394
- }
395
- async updatePreferences(patch) {
396
- const validatedPatch = projectPreferencesPatchSchema.parse(patch);
397
- return this.enqueueMutation(() => this.withConfigLock(async () => {
398
- const config = await this.loadUnlocked();
399
- const current = config.preferences ?? DEFAULT_PROJECT_PREFERENCES;
400
- const next = projectPreferencesSchema.parse({
401
- logs: { ...current.logs, ...validatedPatch.logs },
402
- database: { ...current.database, ...validatedPatch.database },
403
- });
404
- config.preferences = next;
405
- await this.persistUnlocked(config);
406
- return structuredClone(next);
407
- }));
408
- }
409
- async resetPreferences() {
410
- return this.enqueueMutation(() => this.withConfigLock(async () => {
411
- const config = await this.loadUnlocked();
412
- delete config.preferences;
413
- await this.persistUnlocked(config);
414
- return structuredClone(DEFAULT_PROJECT_PREFERENCES);
415
- }));
416
- }
417
- async withConfigLock(operation) {
418
- const lockPath = `${this.configPath}.lock`;
419
- const lock = await acquireConfigLock(lockPath);
420
- try {
421
- return await operation();
422
- }
423
- finally {
424
- await lock.handle.close().finally(() => releaseConfigLock(lockPath, lock.ownerToken));
425
- }
426
- }
427
- enqueueMutation(operation) {
428
- const result = this.mutationQueue.then(operation);
429
- this.mutationQueue = result.then(() => undefined, () => undefined);
430
- return result;
431
- }
432
- mutateConfig(mutation) {
433
- return this.enqueueMutation(() => this.withConfigLock(async () => {
434
- const config = await this.loadUnlocked();
435
- await mutation(config);
436
- await this.persistUnlocked(config);
437
- return config;
438
- }));
439
- }
440
- async registerService(service) {
441
- const parsedService = serviceSchema.parse(service);
442
- return this.mutateConfig((config) => {
443
- config.services = [
444
- ...config.services.filter((item) => item.name !== parsedService.name),
445
- parsedService,
446
- ];
447
- });
448
- }
449
- /** Apply a reviewed import as one config mutation; no partial registration. */
450
- async importServices(services) {
451
- return this.importProjectSetup({ services, databases: [] });
452
- }
453
- /** Atomically applies a reviewed project setup import across both resource kinds. */
454
- async importProjectSetup(input) {
455
- const parsed = input.services.map((service) => ({
456
- definition: serviceSchema.parse(service.definition),
457
- onConflict: service.onConflict,
458
- }));
459
- const parsedDatabases = input.databases.map((database) => ({
460
- definition: databaseSchema.parse({
461
- ...database.definition,
462
- // An import is never authority to unlock writes, including replace.
463
- writeUnlocked: false,
464
- }),
465
- onConflict: database.onConflict,
466
- }));
467
- const importedNames = new Set();
468
- for (const service of parsed) {
469
- if (importedNames.has(service.definition.name)) {
470
- throw new ConfigValidationError(`Import contains duplicate service name: ${service.definition.name}`);
471
- }
472
- importedNames.add(service.definition.name);
473
- }
474
- const importedDatabaseNames = new Set();
475
- for (const database of parsedDatabases) {
476
- if (importedDatabaseNames.has(database.definition.name)) {
477
- throw new ConfigValidationError(`Import contains duplicate database name: ${database.definition.name}`);
478
- }
479
- importedDatabaseNames.add(database.definition.name);
480
- }
481
- return this.mutateConfig((config) => {
482
- const next = [...config.services];
483
- for (const service of parsed) {
484
- const index = next.findIndex((item) => item.name === service.definition.name);
485
- if (index >= 0 && service.onConflict === "error") {
486
- throw new ConfigValidationError(`Service "${service.definition.name}" is already registered.`);
487
- }
488
- if (index >= 0)
489
- next[index] = service.definition;
490
- else
491
- next.push(service.definition);
492
- }
493
- const nextDatabases = [...config.databases];
494
- for (const database of parsedDatabases) {
495
- const index = nextDatabases.findIndex((item) => item.name === database.definition.name);
496
- if (index >= 0 && database.onConflict === "error") {
497
- throw new ConfigValidationError(`Database connection "${database.definition.name}" is already registered.`);
498
- }
499
- if (index >= 0)
500
- nextDatabases[index] = database.definition;
501
- else
502
- nextDatabases.push(database.definition);
503
- }
504
- config.services = next;
505
- config.databases = nextDatabases;
506
- });
507
- }
508
- /**
509
- * Patches only the project assignment. Reassignment goes through here rather
510
- * than `registerService` because that replaces the whole definition by name —
511
- * a caller would have to resend every field, and any field it did not know
512
- * about would be silently dropped.
513
- *
514
- * A blank or absent `projectPath` clears the assignment back to cwd inference.
515
- */
516
- async setServiceProject(name, projectPath) {
517
- const serviceName = name.trim();
518
- if (!serviceName) {
519
- throw new ConfigValidationError("service name is required");
520
- }
521
- const assigned = projectPath?.trim();
522
- return this.mutateConfig((config) => {
523
- const service = config.services.find((item) => item.name === serviceName);
524
- if (!service) {
525
- throw new Error(`Service "${serviceName}" is not registered.`);
526
- }
527
- if (assigned) {
528
- service.projectPath = assigned;
529
- }
530
- else {
531
- delete service.projectPath;
532
- }
533
- });
534
- }
535
- async removeService(name) {
536
- const serviceName = name.trim();
537
- if (!serviceName) {
538
- throw new ConfigValidationError("service name is required");
539
- }
540
- return this.mutateConfig((config) => {
541
- const nextServices = config.services.filter((item) => item.name !== serviceName);
542
- if (nextServices.length === config.services.length) {
543
- throw new Error(`Service "${serviceName}" is not registered.`);
544
- }
545
- config.services = nextServices;
546
- config.bundles = config.bundles.map((bundle) => ({
547
- ...bundle,
548
- services: bundle.services.filter((service) => service !== serviceName),
549
- }));
550
- });
551
- }
552
- async registerBundle(bundle, previousName) {
553
- const parsedBundle = bundleSchema.parse(bundle);
554
- return this.mutateConfig((config) => {
555
- config.bundles = [
556
- ...config.bundles.filter((item) => item.name !== parsedBundle.name && item.name !== previousName),
557
- parsedBundle,
558
- ];
559
- });
560
- }
561
- async registerGitRepository(repository) {
562
- const parsedRepository = gitRepositorySchema.parse(repository);
563
- requireAbsolutePath(parsedRepository.path);
564
- await requireGitWorktree(parsedRepository.path);
565
- return this.mutateConfig((config) => {
566
- const existing = config.gitRepositories.find((item) => item.name === parsedRepository.name);
567
- if (!parsedRepository.githubCredential && existing?.githubCredential) {
568
- parsedRepository.githubCredential = existing.githubCredential;
569
- }
570
- if (!parsedRepository.providerProjects && existing?.providerProjects) {
571
- parsedRepository.providerProjects = existing.providerProjects;
572
- }
573
- config.gitRepositories = [
574
- ...config.gitRepositories.filter((item) => item.name !== parsedRepository.name),
575
- parsedRepository,
576
- ];
577
- config.selectedGitRepository = parsedRepository.name;
578
- });
579
- }
580
- async setGitHubCredential(repositoryName, credential) {
581
- const parsed = githubCredentialSchema.parse(credential);
582
- return this.mutateConfig((config) => {
583
- const repository = config.gitRepositories.find((item) => item.name === repositoryName.trim());
584
- if (!repository) {
585
- throw new Error(`Git repository "${repositoryName}" is not registered.`);
586
- }
587
- repository.githubCredential = parsed;
588
- });
589
- }
590
- async removeGitRepository(name) {
591
- const repositoryName = name.trim();
592
- if (!repositoryName) {
593
- throw new ConfigValidationError("repository name is required");
594
- }
595
- return this.mutateConfig((config) => {
596
- const nextRepositories = config.gitRepositories.filter((repository) => repository.name !== repositoryName);
597
- if (nextRepositories.length === config.gitRepositories.length) {
598
- throw new Error(`Git repository "${repositoryName}" is not registered.`);
599
- }
600
- config.gitRepositories = nextRepositories;
601
- if (config.selectedGitRepository === repositoryName) {
602
- delete config.selectedGitRepository;
603
- }
604
- });
605
- }
606
- /**
607
- * Persist the ordered set of repositories pinned to the board. Names are
608
- * filtered to those still registered, de-duped (order preserved), and capped
609
- * at {@link MAX_BOARD_REPOSITORIES} so a stale, repeated, or overflowing list
610
- * from the client can never corrupt the board or strand repos off-screen.
611
- */
612
- async setGitBoardRepositories(names) {
613
- return this.mutateConfig((config) => {
614
- const registered = new Set(config.gitRepositories.map((repo) => repo.name));
615
- const seen = new Set();
616
- config.gitBoardRepositories = names
617
- .filter((name) => {
618
- if (!registered.has(name) || seen.has(name))
619
- return false;
620
- seen.add(name);
621
- return true;
622
- })
623
- .slice(0, MAX_BOARD_REPOSITORIES);
624
- });
625
- }
626
- async selectGitRepository(name) {
627
- return this.mutateConfig((config) => {
628
- if (!config.gitRepositories.some((repository) => repository.name === name)) {
629
- throw new Error(`Git repository "${name}" is not registered.`);
630
- }
631
- config.selectedGitRepository = name;
632
- });
633
- }
634
- async selectGitWorktree(name, path) {
635
- requireAbsolutePath(path);
636
- const config = await this.load();
637
- const repository = config.gitRepositories.find((item) => item.name === name);
638
- if (!repository) {
639
- throw new Error(`Git repository "${name}" is not registered.`);
640
- }
641
- const worktrees = await new GitWorktreeManager(repository.path).list();
642
- const canonicalPath = await realpath(path).catch(() => path);
643
- const canonicalWorktrees = await Promise.all(worktrees.map((worktree) => realpath(worktree.path).catch(() => worktree.path)));
644
- const selectedIndex = canonicalWorktrees.indexOf(canonicalPath);
645
- if (selectedIndex < 0) {
646
- throw new ConfigValidationError("The selected folder is not a worktree of this project.");
647
- }
648
- const selectedPath = worktrees[selectedIndex].path;
649
- return this.mutateConfig((next) => {
650
- const target = next.gitRepositories.find((item) => item.name === name);
651
- if (target)
652
- target.activeWorktreePath = selectedPath;
653
- });
654
- }
655
- /** Persist which agent CLI the in-dock chat drives. */
656
- async setChatProvider(provider) {
657
- return this.mutateConfig((config) => {
658
- config.chatProvider = provider;
659
- });
660
- }
661
- /**
662
- * Persist the model new sessions for `provider` spawn with. A null/empty
663
- * model clears the pin so the CLI falls back to its own default.
664
- */
665
- async setChatModel(provider, model) {
666
- const trimmed = model?.trim();
667
- return this.mutateConfig((config) => {
668
- const models = { ...config.chatModels };
669
- if (trimmed)
670
- models[provider] = trimmed;
671
- else
672
- delete models[provider];
673
- config.chatModels = models;
674
- });
675
- }
676
- async registerDatabase(database) {
677
- const parsed = databaseSchema.parse(database);
678
- return this.mutateConfig((config) => {
679
- config.databases = [
680
- ...config.databases.filter((item) => item.name !== parsed.name),
681
- parsed,
682
- ];
683
- });
684
- }
685
- async removeDatabase(name) {
686
- return this.mutateConfig((config) => {
687
- config.databases = config.databases.filter((item) => item.name !== name);
688
- });
689
- }
690
- /** Lock or unlock write access for a single connection's SQL console. */
691
- async setDatabaseWriteAccess(name, unlocked) {
692
- return this.mutateConfig((config) => {
693
- const connection = config.databases.find((item) => item.name === name);
694
- if (!connection) {
695
- throw new Error(`Database connection "${name}" is not registered.`);
696
- }
697
- connection.writeUnlocked = unlocked;
698
- });
699
- }
700
- async registerLogSource(source) {
701
- const parsed = logSourceSchema.parse(source);
702
- return this.mutateConfig((config) => {
703
- config.logSources = [
704
- ...config.logSources.filter((item) => item.name !== parsed.name),
705
- parsed,
706
- ];
707
- });
708
- }
709
- async removeLogSource(name) {
710
- return this.mutateConfig((config) => {
711
- config.logSources = config.logSources.filter((item) => item.name !== name);
712
- });
713
- }
714
- async registerSshServer(server) {
715
- const parsed = sshServerSchema.parse(server);
716
- return this.mutateConfig((config) => {
717
- config.sshServers = [
718
- ...config.sshServers.filter((item) => item.host !== parsed.host),
719
- parsed,
720
- ];
721
- });
722
- }
723
- async removeSshServer(host) {
724
- const target = sshServerSchema.shape.host.parse(host);
725
- return this.mutateConfig((config) => {
726
- config.sshServers = config.sshServers.filter((item) => item.host !== target);
727
- });
728
- }
729
- async setGithubToken(host, token, profile) {
730
- const parsed = githubTokenSchema.parse({
731
- host: host.trim(),
732
- token: token.trim(),
733
- login: profile?.login?.trim() || undefined,
734
- avatarUrl: profile?.avatarUrl?.trim() || undefined,
735
- });
736
- return this.mutateConfig((config) => {
737
- config.githubTokens = [
738
- ...config.githubTokens.filter((t) => t.host !== parsed.host),
739
- parsed,
740
- ];
741
- });
742
- }
743
- /** Cached account identity for a stored token, when one was captured. */
744
- getGithubProfile(config, host = "github.com") {
745
- const entry = config.githubTokens.find((t) => t.host === host);
746
- if (!entry?.login)
747
- return undefined;
748
- return { login: entry.login, avatarUrl: entry.avatarUrl };
749
- }
750
- /** Attach identity to an already-stored token without touching the secret. */
751
- async setGithubProfile(host, profile) {
752
- return this.mutateConfig((config) => {
753
- config.githubTokens = config.githubTokens.map((entry) => entry.host === host.trim()
754
- ? { ...entry, login: profile.login, avatarUrl: profile.avatarUrl }
755
- : entry);
756
- });
757
- }
758
- /** Cached commit identity for a GitHub account, when one has been resolved. */
759
- getGithubIdentity(config, host, login) {
760
- return config.githubIdentities.find((entry) => entry.host === host && entry.login.toLowerCase() === login.toLowerCase());
761
- }
762
- async setGithubIdentity(identity) {
763
- const parsed = githubIdentitySchema.parse(identity);
764
- return this.mutateConfig((config) => {
765
- config.githubIdentities = [
766
- ...config.githubIdentities.filter((entry) => entry.host !== parsed.host ||
767
- entry.login.toLowerCase() !== parsed.login.toLowerCase()),
768
- parsed,
769
- ];
770
- });
771
- }
772
- async removeGithubToken(host) {
773
- return this.mutateConfig((config) => {
774
- config.githubTokens = config.githubTokens.filter((t) => t.host !== host.trim());
775
- });
776
- }
777
- getGithubToken(config, host = "github.com") {
778
- return config.githubTokens.find((t) => t.host === host)?.token;
779
- }
780
- /**
781
- * Save how a provider is connected. A `cli` connection deliberately drops any
782
- * token it was handed: the vendor CLI's auth file stays the single source, so
783
- * `vercel logout` also revokes us instead of leaving a stale copy behind.
784
- */
785
- async setConnection(providerId, connection) {
786
- const id = providerIdSchema.parse(providerId);
787
- const parsed = providerConnectionSchema.parse(connection);
788
- if (parsed.source === "cli") {
789
- delete parsed.token;
790
- }
791
- else if (!parsed.token) {
792
- throw new ConfigValidationError(`a ${providerLabel(id)} token is required`);
793
- }
794
- if (parsed.source === "oauth" && !parsed.clientId) {
795
- throw new ConfigValidationError(`a ${providerLabel(id)} OAuth connection needs its client id`);
796
- }
797
- return this.mutateConfig((config) => {
798
- config.connections[id] = parsed;
799
- });
800
- }
801
- /**
802
- * Persist the tokens a refresh returned. Separate from
803
- * {@link setConnection} because it runs mid-request on an already connected
804
- * account, and must not disturb the scope or cached username.
805
- */
806
- async updateConnectionTokens(providerId, tokens) {
807
- const id = providerIdSchema.parse(providerId);
808
- return this.mutateConfig((config) => {
809
- const connection = config.connections[id];
810
- if (connection?.source !== "oauth")
811
- return;
812
- config.connections[id] = {
813
- ...connection,
814
- token: tokens.token,
815
- // Providers rotate refresh tokens; keep the previous one only if this
816
- // response omitted a replacement, or the connection becomes unrenewable.
817
- refreshToken: tokens.refreshToken ?? connection.refreshToken,
818
- expiresAt: tokens.expiresAt,
819
- };
820
- });
821
- }
822
- /** Re-scope an existing connection without re-entering the token. */
823
- async setConnectionScope(providerId, scope) {
824
- const id = providerIdSchema.parse(providerId);
825
- return this.mutateConfig((config) => {
826
- const connection = config.connections[id];
827
- if (!connection)
828
- throw new Error(`${providerLabel(id)} is not connected.`);
829
- config.connections[id] = {
830
- ...connection,
831
- scopeId: scope.scopeId?.trim() || undefined,
832
- scopeSlug: scope.scopeSlug?.trim() || undefined,
833
- };
834
- });
835
- }
836
- async removeConnection(providerId) {
837
- const id = providerIdSchema.parse(providerId);
838
- return this.mutateConfig((config) => {
839
- delete config.connections[id];
840
- });
841
- }
842
- /** Pin which provider project a registered repository deploys. */
843
- async setProviderProject(providerId, repositoryName, projectId) {
844
- const id = providerIdSchema.parse(providerId);
845
- return this.mutateConfig((config) => {
846
- const repository = config.gitRepositories.find((item) => item.name === repositoryName.trim());
847
- if (!repository) {
848
- throw new Error(`Git repository "${repositoryName}" is not registered.`);
849
- }
850
- const pinned = projectId?.trim();
851
- const projects = { ...repository.providerProjects };
852
- if (pinned)
853
- projects[id] = pinned;
854
- else
855
- delete projects[id];
856
- // Drop the key entirely when nothing is pinned, so an untouched repo
857
- // serializes exactly as it did before providers were introduced.
858
- if (Object.keys(projects).length > 0)
859
- repository.providerProjects = projects;
860
- else
861
- delete repository.providerProjects;
862
- });
863
- }
864
- /** Persist a user-saved/forked workflow (replaces one with the same id). */
865
- async saveWorkflow(workflow) {
866
- const parsed = workflowSchema.parse(workflow);
867
- return this.mutateConfig((config) => {
868
- config.workflows = [
869
- ...config.workflows.filter((item) => item.id !== parsed.id),
870
- parsed,
871
- ];
872
- });
873
- }
874
- async removeWorkflow(id) {
875
- return this.mutateConfig((config) => {
876
- config.workflows = config.workflows.filter((item) => item.id !== id.trim());
877
- });
878
- }
879
- /** Persist an event→workflow trigger (replaces one with the same id). */
880
- async saveWorkflowTrigger(trigger) {
881
- const parsed = workflowTriggerSchema.parse(trigger);
882
- return this.mutateConfig((config) => {
883
- config.workflowTriggers = [
884
- ...config.workflowTriggers.filter((item) => item.id !== parsed.id),
885
- parsed,
886
- ];
887
- });
888
- }
889
- async removeWorkflowTrigger(id) {
890
- return this.mutateConfig((config) => {
891
- config.workflowTriggers = config.workflowTriggers.filter((item) => item.id !== id.trim());
892
- });
893
- }
894
- }
895
- export class ConfigValidationError extends Error {
896
- }
897
- function requireAbsolutePath(path) {
898
- if (!isAbsolute(path)) {
899
- throw new ConfigValidationError("Please add an absolute path. Paths beginning with ~ are not expanded here.");
900
- }
901
- }
902
- export async function isGitWorktree(path) {
903
- try {
904
- const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: path });
905
- return stdout.trim() === "true";
906
- }
907
- catch {
908
- return false;
909
- }
910
- }
911
- /**
912
- * The worktree root enclosing `path`, or null when it is not inside a repo.
913
- *
914
- * Registering a service's own `cwd` is usually the wrong granularity — a service
915
- * often runs from a subdirectory (`repo/frontend`), and a project pinned there
916
- * would fight the path-based grouping. Resolving to the root first is what makes
917
- * "adopt this service's folder" produce the project the user actually meant.
918
- */
919
- export async function gitToplevel(path) {
920
- try {
921
- const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
922
- cwd: path,
923
- });
924
- return stdout.trim() || null;
925
- }
926
- catch {
927
- return null;
928
- }
929
- }
930
- async function requireGitWorktree(path) {
931
- if (await isGitWorktree(path))
932
- return;
933
- throw new ConfigValidationError("Not a Git repository. Choose a folder inside a Git worktree.");
934
- }
935
- async function acquireConfigLock(lockPath) {
936
- await mkdir(dirname(lockPath), { recursive: true });
937
- const startedAt = Date.now();
938
- let attempts = 0;
939
- while (Date.now() - startedAt < CONFIG_LOCK_WAIT_MS) {
940
- try {
941
- const handle = await open(lockPath, "wx");
942
- const ownerToken = `${process.pid}:${randomUUID()}`;
943
- try {
944
- await handle.writeFile(ownerToken, "utf8");
945
- return { handle, ownerToken };
946
- }
947
- catch (error) {
948
- await handle.close().catch(() => undefined);
949
- await unlink(lockPath).catch(() => undefined);
950
- throw error;
951
- }
952
- }
953
- catch (error) {
954
- if (!hasErrorCode(error, "EEXIST"))
955
- throw error;
956
- }
957
- if (await recoverStaleConfigLock(lockPath)) {
958
- continue;
959
- }
960
- attempts += 1;
961
- const retryDelay = Math.min(CONFIG_LOCK_RETRY_MIN_MS * attempts, CONFIG_LOCK_RETRY_MAX_MS);
962
- await new Promise((resolveDelay) => {
963
- setTimeout(resolveDelay, retryDelay);
964
- });
965
- }
966
- throw new Error(`Timed out waiting for config lock: ${lockPath}`);
967
- }
968
- async function releaseConfigLock(lockPath, ownerToken) {
969
- let currentOwner;
970
- try {
971
- currentOwner = await readFile(lockPath, "utf8");
972
- }
973
- catch (error) {
974
- if (hasErrorCode(error, "ENOENT"))
975
- return true;
976
- throw error;
977
- }
978
- if (currentOwner !== ownerToken)
979
- return false;
980
- try {
981
- await unlink(lockPath);
982
- }
983
- catch (error) {
984
- if (!hasErrorCode(error, "ENOENT"))
985
- throw error;
986
- }
987
- return true;
988
- }
989
- async function recoverStaleConfigLock(lockPath, afterOwnerRead) {
990
- let observedOwner;
991
- try {
992
- observedOwner = await readFile(lockPath, "utf8");
993
- }
994
- catch (error) {
995
- if (hasErrorCode(error, "ENOENT"))
996
- return true;
997
- throw error;
998
- }
999
- await afterOwnerRead?.();
1000
- let lockMtimeMs;
1001
- try {
1002
- lockMtimeMs = (await stat(lockPath)).mtimeMs;
1003
- }
1004
- catch (error) {
1005
- if (hasErrorCode(error, "ENOENT"))
1006
- return true;
1007
- throw error;
1008
- }
1009
- if (Date.now() - lockMtimeMs <= CONFIG_LOCK_STALE_MS)
1010
- return false;
1011
- return releaseConfigLock(lockPath, observedOwner);
1012
- }
1013
- /** @internal Deterministic stale-lock ownership seam used by regression tests. */
1014
- export async function __recoverStaleConfigLockForTests(lockPath, afterOwnerRead) {
1015
- await recoverStaleConfigLock(lockPath, afterOwnerRead);
1016
- }
1017
- function hasErrorCode(error, code) {
1018
- return (typeof error === "object" &&
1019
- error !== null &&
1020
- "code" in error &&
1021
- error.code === code);
1022
- }
1023
- function isMissingFileError(error) {
1024
- return hasErrorCode(error, "ENOENT");
1025
- }
1026
- //# sourceMappingURL=config-store.js.map