@jungjaehoon/mama-os 0.77.0 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/README.md +59 -30
  3. package/db/migrations/002-model-runs-parent-index.sql +11 -0
  4. package/db/migrations/003-upkeep-settled.sql +15 -0
  5. package/dist/api/google-read-actions.d.ts +30 -0
  6. package/dist/api/google-read-actions.d.ts.map +1 -0
  7. package/dist/api/google-read-actions.js +256 -0
  8. package/dist/api/google-read-actions.js.map +1 -0
  9. package/dist/api/record-actions.d.ts.map +1 -1
  10. package/dist/api/record-actions.js +23 -5
  11. package/dist/api/record-actions.js.map +1 -1
  12. package/dist/api/report-handler.d.ts +0 -6
  13. package/dist/api/report-handler.d.ts.map +1 -1
  14. package/dist/api/report-handler.js +0 -54
  15. package/dist/api/report-handler.js.map +1 -1
  16. package/dist/api/security-events.d.ts +1 -1
  17. package/dist/api/security-events.d.ts.map +1 -1
  18. package/dist/api/security-events.js +10 -1
  19. package/dist/api/security-events.js.map +1 -1
  20. package/dist/api/source-actions.d.ts +9 -0
  21. package/dist/api/source-actions.d.ts.map +1 -1
  22. package/dist/api/source-actions.js +49 -0
  23. package/dist/api/source-actions.js.map +1 -1
  24. package/dist/api/viewer-request-security.d.ts +14 -1
  25. package/dist/api/viewer-request-security.d.ts.map +1 -1
  26. package/dist/api/viewer-request-security.js +26 -3
  27. package/dist/api/viewer-request-security.js.map +1 -1
  28. package/dist/api/viewer-server.d.ts +8 -0
  29. package/dist/api/viewer-server.d.ts.map +1 -1
  30. package/dist/api/viewer-server.js +66 -0
  31. package/dist/api/viewer-server.js.map +1 -1
  32. package/dist/api/work-actions.d.ts +19 -2
  33. package/dist/api/work-actions.d.ts.map +1 -1
  34. package/dist/api/work-actions.js +42 -2
  35. package/dist/api/work-actions.js.map +1 -1
  36. package/dist/cli/commands/backfill.d.ts.map +1 -1
  37. package/dist/cli/commands/backfill.js +1 -0
  38. package/dist/cli/commands/backfill.js.map +1 -1
  39. package/dist/cli/commands/backup.d.ts +14 -0
  40. package/dist/cli/commands/backup.d.ts.map +1 -0
  41. package/dist/cli/commands/backup.js +174 -0
  42. package/dist/cli/commands/backup.js.map +1 -0
  43. package/dist/cli/commands/control.d.ts +44 -0
  44. package/dist/cli/commands/control.d.ts.map +1 -0
  45. package/dist/cli/commands/control.js +354 -0
  46. package/dist/cli/commands/control.js.map +1 -0
  47. package/dist/cli/commands/daemon.d.ts +60 -3
  48. package/dist/cli/commands/daemon.d.ts.map +1 -1
  49. package/dist/cli/commands/daemon.js +454 -78
  50. package/dist/cli/commands/daemon.js.map +1 -1
  51. package/dist/cli/commands/doctor.d.ts +13 -0
  52. package/dist/cli/commands/doctor.d.ts.map +1 -0
  53. package/dist/cli/commands/doctor.js +216 -0
  54. package/dist/cli/commands/doctor.js.map +1 -0
  55. package/dist/cli/commands/init-questions.d.ts +98 -0
  56. package/dist/cli/commands/init-questions.d.ts.map +1 -0
  57. package/dist/cli/commands/init-questions.js +420 -0
  58. package/dist/cli/commands/init-questions.js.map +1 -0
  59. package/dist/cli/commands/init-section.d.ts +13 -0
  60. package/dist/cli/commands/init-section.d.ts.map +1 -0
  61. package/dist/cli/commands/init-section.js +375 -0
  62. package/dist/cli/commands/init-section.js.map +1 -0
  63. package/dist/cli/commands/init.d.ts +56 -2
  64. package/dist/cli/commands/init.d.ts.map +1 -1
  65. package/dist/cli/commands/init.js +562 -350
  66. package/dist/cli/commands/init.js.map +1 -1
  67. package/dist/cli/commands/logs.d.ts +9 -0
  68. package/dist/cli/commands/logs.d.ts.map +1 -0
  69. package/dist/cli/commands/logs.js +109 -0
  70. package/dist/cli/commands/logs.js.map +1 -0
  71. package/dist/cli/commands/node-move.d.ts +20 -0
  72. package/dist/cli/commands/node-move.d.ts.map +1 -0
  73. package/dist/cli/commands/node-move.js +289 -0
  74. package/dist/cli/commands/node-move.js.map +1 -0
  75. package/dist/cli/commands/register-owner.d.ts +3 -0
  76. package/dist/cli/commands/register-owner.d.ts.map +1 -1
  77. package/dist/cli/commands/register-owner.js +14 -0
  78. package/dist/cli/commands/register-owner.js.map +1 -1
  79. package/dist/cli/commands/restore.d.ts +16 -0
  80. package/dist/cli/commands/restore.d.ts.map +1 -0
  81. package/dist/cli/commands/restore.js +137 -0
  82. package/dist/cli/commands/restore.js.map +1 -0
  83. package/dist/cli/commands/service.d.ts +44 -0
  84. package/dist/cli/commands/service.d.ts.map +1 -0
  85. package/dist/cli/commands/service.js +306 -0
  86. package/dist/cli/commands/service.js.map +1 -0
  87. package/dist/cli/commands/tools.d.ts +1 -1
  88. package/dist/cli/commands/tools.d.ts.map +1 -1
  89. package/dist/cli/commands/tools.js +8 -3
  90. package/dist/cli/commands/tools.js.map +1 -1
  91. package/dist/cli/commands/uninstall.d.ts +7 -0
  92. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  93. package/dist/cli/commands/uninstall.js +335 -0
  94. package/dist/cli/commands/uninstall.js.map +1 -0
  95. package/dist/cli/commands/update.d.ts +59 -0
  96. package/dist/cli/commands/update.d.ts.map +1 -0
  97. package/dist/cli/commands/update.js +948 -0
  98. package/dist/cli/commands/update.js.map +1 -0
  99. package/dist/cli/index.js +74 -23
  100. package/dist/cli/index.js.map +1 -1
  101. package/dist/cli/launch-files.d.ts +119 -0
  102. package/dist/cli/launch-files.d.ts.map +1 -1
  103. package/dist/cli/launch-files.js +324 -15
  104. package/dist/cli/launch-files.js.map +1 -1
  105. package/dist/cli/prompt.d.ts +2 -1
  106. package/dist/cli/prompt.d.ts.map +1 -1
  107. package/dist/cli/prompt.js +5 -2
  108. package/dist/cli/prompt.js.map +1 -1
  109. package/dist/cli/runtime/backend-probe.d.ts +34 -0
  110. package/dist/cli/runtime/backend-probe.d.ts.map +1 -0
  111. package/dist/cli/runtime/backend-probe.js +83 -0
  112. package/dist/cli/runtime/backend-probe.js.map +1 -0
  113. package/dist/cli/runtime/backup.d.ts +130 -0
  114. package/dist/cli/runtime/backup.d.ts.map +1 -0
  115. package/dist/cli/runtime/backup.js +592 -0
  116. package/dist/cli/runtime/backup.js.map +1 -0
  117. package/dist/cli/runtime/daemon-control.d.ts +169 -0
  118. package/dist/cli/runtime/daemon-control.d.ts.map +1 -0
  119. package/dist/cli/runtime/daemon-control.js +441 -0
  120. package/dist/cli/runtime/daemon-control.js.map +1 -0
  121. package/dist/cli/runtime/default-roots.d.ts +27 -0
  122. package/dist/cli/runtime/default-roots.d.ts.map +1 -0
  123. package/dist/cli/runtime/default-roots.js +61 -0
  124. package/dist/cli/runtime/default-roots.js.map +1 -0
  125. package/dist/cli/runtime/diagnostics.d.ts +68 -0
  126. package/dist/cli/runtime/diagnostics.d.ts.map +1 -0
  127. package/dist/cli/runtime/diagnostics.js +1139 -0
  128. package/dist/cli/runtime/diagnostics.js.map +1 -0
  129. package/dist/cli/runtime/init-state.d.ts +20 -0
  130. package/dist/cli/runtime/init-state.d.ts.map +1 -0
  131. package/dist/cli/runtime/init-state.js +51 -0
  132. package/dist/cli/runtime/init-state.js.map +1 -0
  133. package/dist/cli/runtime/install-kind.d.ts +54 -0
  134. package/dist/cli/runtime/install-kind.d.ts.map +1 -0
  135. package/dist/cli/runtime/install-kind.js +164 -0
  136. package/dist/cli/runtime/install-kind.js.map +1 -0
  137. package/dist/cli/runtime/node-move-journal.d.ts +44 -0
  138. package/dist/cli/runtime/node-move-journal.d.ts.map +1 -0
  139. package/dist/cli/runtime/node-move-journal.js +48 -0
  140. package/dist/cli/runtime/node-move-journal.js.map +1 -0
  141. package/dist/cli/runtime/release-check.d.ts +94 -0
  142. package/dist/cli/runtime/release-check.d.ts.map +1 -0
  143. package/dist/cli/runtime/release-check.js +316 -0
  144. package/dist/cli/runtime/release-check.js.map +1 -0
  145. package/dist/cli/runtime/restore.d.ts +98 -0
  146. package/dist/cli/runtime/restore.d.ts.map +1 -0
  147. package/dist/cli/runtime/restore.js +756 -0
  148. package/dist/cli/runtime/restore.js.map +1 -0
  149. package/dist/cli/runtime/setup-page.d.ts +57 -0
  150. package/dist/cli/runtime/setup-page.d.ts.map +1 -0
  151. package/dist/cli/runtime/setup-page.js +266 -0
  152. package/dist/cli/runtime/setup-page.js.map +1 -0
  153. package/dist/cli/runtime/source-tools.d.ts +60 -0
  154. package/dist/cli/runtime/source-tools.d.ts.map +1 -0
  155. package/dist/cli/runtime/source-tools.js +170 -0
  156. package/dist/cli/runtime/source-tools.js.map +1 -0
  157. package/dist/cli/runtime/systemd-service.d.ts +13 -0
  158. package/dist/cli/runtime/systemd-service.d.ts.map +1 -0
  159. package/dist/cli/runtime/systemd-service.js +32 -0
  160. package/dist/cli/runtime/systemd-service.js.map +1 -0
  161. package/dist/cli/runtime/telegram-pairing.d.ts +73 -0
  162. package/dist/cli/runtime/telegram-pairing.d.ts.map +1 -0
  163. package/dist/cli/runtime/telegram-pairing.js +184 -0
  164. package/dist/cli/runtime/telegram-pairing.js.map +1 -0
  165. package/dist/cli/runtime/update-journal.d.ts +135 -0
  166. package/dist/cli/runtime/update-journal.d.ts.map +1 -0
  167. package/dist/cli/runtime/update-journal.js +144 -0
  168. package/dist/cli/runtime/update-journal.js.map +1 -0
  169. package/dist/cli/runtime/update-progress.d.ts +95 -0
  170. package/dist/cli/runtime/update-progress.d.ts.map +1 -0
  171. package/dist/cli/runtime/update-progress.js +154 -0
  172. package/dist/cli/runtime/update-progress.js.map +1 -0
  173. package/dist/cli/runtime/update-request.d.ts +58 -0
  174. package/dist/cli/runtime/update-request.d.ts.map +1 -0
  175. package/dist/cli/runtime/update-request.js +172 -0
  176. package/dist/cli/runtime/update-request.js.map +1 -0
  177. package/dist/connectors/calendar/index.d.ts +5 -1
  178. package/dist/connectors/calendar/index.d.ts.map +1 -1
  179. package/dist/connectors/calendar/index.js +19 -28
  180. package/dist/connectors/calendar/index.js.map +1 -1
  181. package/dist/connectors/chatwork/index.d.ts.map +1 -1
  182. package/dist/connectors/chatwork/index.js +7 -3
  183. package/dist/connectors/chatwork/index.js.map +1 -1
  184. package/dist/connectors/config-loader.d.ts +7 -1
  185. package/dist/connectors/config-loader.d.ts.map +1 -1
  186. package/dist/connectors/config-loader.js +11 -2
  187. package/dist/connectors/config-loader.js.map +1 -1
  188. package/dist/connectors/discord/index.d.ts.map +1 -1
  189. package/dist/connectors/discord/index.js +4 -3
  190. package/dist/connectors/discord/index.js.map +1 -1
  191. package/dist/connectors/drive/index.d.ts.map +1 -1
  192. package/dist/connectors/drive/index.js +15 -13
  193. package/dist/connectors/drive/index.js.map +1 -1
  194. package/dist/connectors/framework/gws-utils.d.ts +62 -0
  195. package/dist/connectors/framework/gws-utils.d.ts.map +1 -1
  196. package/dist/connectors/framework/gws-utils.js +133 -3
  197. package/dist/connectors/framework/gws-utils.js.map +1 -1
  198. package/dist/connectors/framework/polling-scheduler.d.ts.map +1 -1
  199. package/dist/connectors/framework/polling-scheduler.js +12 -11
  200. package/dist/connectors/framework/polling-scheduler.js.map +1 -1
  201. package/dist/connectors/framework/types.d.ts +24 -0
  202. package/dist/connectors/framework/types.d.ts.map +1 -1
  203. package/dist/connectors/framework/types.js +9 -0
  204. package/dist/connectors/framework/types.js.map +1 -1
  205. package/dist/connectors/gmail/index.d.ts.map +1 -1
  206. package/dist/connectors/gmail/index.js +14 -13
  207. package/dist/connectors/gmail/index.js.map +1 -1
  208. package/dist/connectors/imessage/index.d.ts.map +1 -1
  209. package/dist/connectors/imessage/index.js +2 -1
  210. package/dist/connectors/imessage/index.js.map +1 -1
  211. package/dist/connectors/index.d.ts +4 -4
  212. package/dist/connectors/index.d.ts.map +1 -1
  213. package/dist/connectors/index.js +4 -10
  214. package/dist/connectors/index.js.map +1 -1
  215. package/dist/connectors/notion/index.d.ts.map +1 -1
  216. package/dist/connectors/notion/index.js +5 -3
  217. package/dist/connectors/notion/index.js.map +1 -1
  218. package/dist/connectors/sheets/index.d.ts.map +1 -1
  219. package/dist/connectors/sheets/index.js +17 -12
  220. package/dist/connectors/sheets/index.js.map +1 -1
  221. package/dist/connectors/slack/index.d.ts.map +1 -1
  222. package/dist/connectors/slack/index.js +9 -3
  223. package/dist/connectors/slack/index.js.map +1 -1
  224. package/dist/connectors/telegram/index.d.ts.map +1 -1
  225. package/dist/connectors/telegram/index.js +4 -3
  226. package/dist/connectors/telegram/index.js.map +1 -1
  227. package/dist/connectors/trello/index.d.ts +1 -1
  228. package/dist/connectors/trello/index.d.ts.map +1 -1
  229. package/dist/connectors/trello/index.js +10 -5
  230. package/dist/connectors/trello/index.js.map +1 -1
  231. package/dist/gateways/discord.d.ts +6 -0
  232. package/dist/gateways/discord.d.ts.map +1 -1
  233. package/dist/gateways/discord.js +38 -27
  234. package/dist/gateways/discord.js.map +1 -1
  235. package/dist/gateways/slack.d.ts +6 -0
  236. package/dist/gateways/slack.d.ts.map +1 -1
  237. package/dist/gateways/slack.js +38 -27
  238. package/dist/gateways/slack.js.map +1 -1
  239. package/dist/gateways/telegram-commands.d.ts +124 -0
  240. package/dist/gateways/telegram-commands.d.ts.map +1 -0
  241. package/dist/gateways/telegram-commands.js +131 -0
  242. package/dist/gateways/telegram-commands.js.map +1 -0
  243. package/dist/gateways/telegram.d.ts +20 -0
  244. package/dist/gateways/telegram.d.ts.map +1 -1
  245. package/dist/gateways/telegram.js +138 -34
  246. package/dist/gateways/telegram.js.map +1 -1
  247. package/dist/gateways/turn-contract.d.ts +11 -0
  248. package/dist/gateways/turn-contract.d.ts.map +1 -1
  249. package/dist/runtime/action-surface.d.ts +1 -1
  250. package/dist/runtime/action-surface.d.ts.map +1 -1
  251. package/dist/runtime/action-surface.js +10 -0
  252. package/dist/runtime/action-surface.js.map +1 -1
  253. package/dist/runtime/backend-security.d.ts +26 -2
  254. package/dist/runtime/backend-security.d.ts.map +1 -1
  255. package/dist/runtime/backend-security.js +63 -10
  256. package/dist/runtime/backend-security.js.map +1 -1
  257. package/dist/runtime/config.d.ts +3 -0
  258. package/dist/runtime/config.d.ts.map +1 -1
  259. package/dist/runtime/config.js +4 -4
  260. package/dist/runtime/config.js.map +1 -1
  261. package/dist/runtime/connectors.d.ts +21 -1
  262. package/dist/runtime/connectors.d.ts.map +1 -1
  263. package/dist/runtime/connectors.js +28 -17
  264. package/dist/runtime/connectors.js.map +1 -1
  265. package/dist/runtime/core-db.d.ts.map +1 -1
  266. package/dist/runtime/core-db.js +2 -0
  267. package/dist/runtime/core-db.js.map +1 -1
  268. package/dist/runtime/member-paths.d.ts +15 -7
  269. package/dist/runtime/member-paths.d.ts.map +1 -1
  270. package/dist/runtime/member-paths.js +64 -12
  271. package/dist/runtime/member-paths.js.map +1 -1
  272. package/dist/runtime/member-session.d.ts +4 -0
  273. package/dist/runtime/member-session.d.ts.map +1 -1
  274. package/dist/runtime/member-session.js +23 -2
  275. package/dist/runtime/member-session.js.map +1 -1
  276. package/dist/runtime/native-session.d.ts +2 -0
  277. package/dist/runtime/native-session.d.ts.map +1 -1
  278. package/dist/runtime/native-session.js +1 -0
  279. package/dist/runtime/native-session.js.map +1 -1
  280. package/dist/runtime/owner-runtime.d.ts +63 -1
  281. package/dist/runtime/owner-runtime.d.ts.map +1 -1
  282. package/dist/runtime/owner-runtime.js +180 -3
  283. package/dist/runtime/owner-runtime.js.map +1 -1
  284. package/dist/runtime/owner-system-prompt.d.ts.map +1 -1
  285. package/dist/runtime/owner-system-prompt.js +6 -5
  286. package/dist/runtime/owner-system-prompt.js.map +1 -1
  287. package/dist/runtime/principal-access.d.ts +2 -0
  288. package/dist/runtime/principal-access.d.ts.map +1 -1
  289. package/dist/runtime/principal-access.js +7 -0
  290. package/dist/runtime/principal-access.js.map +1 -1
  291. package/dist/runtime/principal-sessions.d.ts.map +1 -1
  292. package/dist/runtime/principal-sessions.js +8 -1
  293. package/dist/runtime/principal-sessions.js.map +1 -1
  294. package/dist/runtime/record-orders.d.ts.map +1 -1
  295. package/dist/runtime/record-orders.js +3 -29
  296. package/dist/runtime/record-orders.js.map +1 -1
  297. package/dist/runtime/report-scheduler.d.ts +9 -2
  298. package/dist/runtime/report-scheduler.d.ts.map +1 -1
  299. package/dist/runtime/report-scheduler.js +37 -10
  300. package/dist/runtime/report-scheduler.js.map +1 -1
  301. package/dist/runtime/rotating-log.d.ts +44 -0
  302. package/dist/runtime/rotating-log.d.ts.map +1 -0
  303. package/dist/runtime/rotating-log.js +124 -0
  304. package/dist/runtime/rotating-log.js.map +1 -0
  305. package/dist/runtime/stimulus-delivery.d.ts +3 -0
  306. package/dist/runtime/stimulus-delivery.d.ts.map +1 -1
  307. package/dist/runtime/stimulus-delivery.js +19 -3
  308. package/dist/runtime/stimulus-delivery.js.map +1 -1
  309. package/dist/runtime/tools-paths.d.ts +7 -0
  310. package/dist/runtime/tools-paths.d.ts.map +1 -1
  311. package/dist/runtime/tools-paths.js +11 -5
  312. package/dist/runtime/tools-paths.js.map +1 -1
  313. package/dist/runtime/upkeep-close.d.ts +17 -0
  314. package/dist/runtime/upkeep-close.d.ts.map +1 -0
  315. package/dist/runtime/upkeep-close.js +127 -0
  316. package/dist/runtime/upkeep-close.js.map +1 -0
  317. package/dist/runtime/upkeep-orders.d.ts +124 -0
  318. package/dist/runtime/upkeep-orders.d.ts.map +1 -0
  319. package/dist/runtime/upkeep-orders.js +310 -0
  320. package/dist/runtime/upkeep-orders.js.map +1 -0
  321. package/dist/runtime/upkeep-reconcile.d.ts +25 -0
  322. package/dist/runtime/upkeep-reconcile.d.ts.map +1 -0
  323. package/dist/runtime/upkeep-reconcile.js +231 -0
  324. package/dist/runtime/upkeep-reconcile.js.map +1 -0
  325. package/dist/runtime/upkeep-writeback.d.ts +22 -0
  326. package/dist/runtime/upkeep-writeback.d.ts.map +1 -0
  327. package/dist/runtime/upkeep-writeback.js +203 -0
  328. package/dist/runtime/upkeep-writeback.js.map +1 -0
  329. package/dist/tools/document-toolkit.d.ts +2 -0
  330. package/dist/tools/document-toolkit.d.ts.map +1 -1
  331. package/dist/tools/document-toolkit.js +2 -0
  332. package/dist/tools/document-toolkit.js.map +1 -1
  333. package/dist/utils/untrusted-content.d.ts.map +1 -1
  334. package/dist/utils/untrusted-content.js +8 -1
  335. package/dist/utils/untrusted-content.js.map +1 -1
  336. package/install/install.sh +457 -0
  337. package/install/node.json +9 -0
  338. package/package.json +5 -5
@@ -0,0 +1,169 @@
1
+ import { CliInputError } from '../prompt.js';
2
+ /**
3
+ * One install runs one process that owns its stores: the daemon, or a replay or backfill booted
4
+ * the same way, or register-owner. Its claim is an exclusive SQLite lock on `runtime/daemon.lock`,
5
+ * held for the process's life and released by the operating system when the process ends, so a
6
+ * crash, a reboot or a reused pid never leaves a claim behind. `runtime/daemon.holder.json` names
7
+ * the holder for `mama status`. The token for the control socket also lives under `runtime/`,
8
+ * which the agents' native reads deny, so a session that reaches the socket still cannot use it.
9
+ * The socket sits beside `runtime.sock` at the root, so it fits the same AF_UNIX path limit
10
+ * (104 bytes on macOS).
11
+ */
12
+ export interface DaemonControlPaths {
13
+ readonly lockPath: string;
14
+ readonly holderPath: string;
15
+ readonly socketPath: string;
16
+ readonly tokenPath: string;
17
+ }
18
+ /** A lock and the file naming its holder: the install's, or another one such as `update.lock`. */
19
+ export type LockPaths = Pick<DaemonControlPaths, 'lockPath' | 'holderPath'>;
20
+ export declare function daemonControlPaths(mamaRoot: string): DaemonControlPaths;
21
+ /** The journal an interrupted `mama restore` leaves; nothing may run on the install while it is there. */
22
+ export declare function restoreJournalPath(mamaRoot: string): string;
23
+ /** A half-switched install: a refusal, not a failure, so a service does not restart into it. */
24
+ export declare class RestorePendingError extends CliInputError {
25
+ readonly code = "MAMA_RESTORE_PENDING";
26
+ constructor();
27
+ }
28
+ /** Refuse to work on an install while a restore journal is open. */
29
+ export declare function refuseWhileRestoring(mamaRoot: string): void;
30
+ export interface LockOwner {
31
+ readonly pid: number;
32
+ readonly command: string;
33
+ readonly startedAt: number;
34
+ readonly nonce: string;
35
+ }
36
+ /** A CLI input error: the message names the holder and the fix, and carries no secret. */
37
+ export declare class InstallBusyError extends CliInputError {
38
+ readonly holder: LockOwner | null;
39
+ readonly code = "MAMA_INSTALL_BUSY";
40
+ constructor(holder: LockOwner | null, lockPath: string);
41
+ }
42
+ export interface InstallLock {
43
+ readonly owner: LockOwner;
44
+ release(): void;
45
+ }
46
+ /**
47
+ * Take the install's lock: an exclusive transaction on the lock database, kept open for the
48
+ * process's life. A held lock refuses after `busyTimeoutMs`, which only outlasts the moment a
49
+ * `mama status` probe reads the file.
50
+ */
51
+ export declare function acquireInstallLock(paths: LockPaths, command: string, options?: {
52
+ busyTimeoutMs?: number;
53
+ }): InstallLock;
54
+ /**
55
+ * The process that holds the install, or null when none does. Reading the lock database needs a
56
+ * shared lock, which the holder's exclusive one refuses; when nothing holds it, the read takes the
57
+ * shared lock for an instant only.
58
+ */
59
+ export declare function lockHolder(paths: LockPaths): LockOwner | null;
60
+ export type DaemonControlOp = 'status' | 'stop' | 'probe' | 'drain' | 'release';
61
+ /** What a drain waits for: model runs of this boot still running, and inputs a delivery owns. */
62
+ export interface DrainCounts {
63
+ readonly running: number;
64
+ readonly claimed: number;
65
+ }
66
+ /** Claims held for one drain connection, from `hold` until `release`. */
67
+ export interface ClaimHold {
68
+ /** How long the drain may wait, fixed when the hold began. */
69
+ readonly boundMs: number;
70
+ counts(): DrainCounts;
71
+ release(): void;
72
+ }
73
+ export interface DaemonControlHandlers {
74
+ status(): Promise<Record<string, unknown>> | Record<string, unknown>;
75
+ stop(): void;
76
+ /** One real backend turn; it throws what failed. */
77
+ probe(): Promise<Record<string, unknown>>;
78
+ /** Stop claiming new work until the hold is released; it throws when it cannot hold. */
79
+ hold(): ClaimHold;
80
+ /**
81
+ * End the hold an update candidate boots with (docs/development/work/update.md, step 14);
82
+ * `held` says whether there was one.
83
+ */
84
+ release(): {
85
+ held: boolean;
86
+ };
87
+ }
88
+ export interface DaemonControlServer {
89
+ close(): Promise<void>;
90
+ }
91
+ /** A drain repeats its counts this often while they stay the same, so a waiting terminal sees why. */
92
+ export declare const DRAIN_REPEAT_MS = 30000;
93
+ /**
94
+ * Serve status, stop, a backend probe, a drain and an update's release to the CLI. Only the lock holder calls this, so
95
+ * removing a socket left by a dead holder never removes a live one. Each boot writes a new token; a
96
+ * request without it is refused. Every op but `drain` answers once and ends the connection. A
97
+ * drain keeps its connection open and holds claims for as long as it stays open: it sends its
98
+ * counts as lines until nothing runs, then says idle and goes on holding, so the stop that follows
99
+ * starts nothing new; a client that dies lets go. Past the hold's bound it sends the counts and
100
+ * ends, which lets go too.
101
+ */
102
+ export declare function startDaemonControl(paths: DaemonControlPaths, handlers: DaemonControlHandlers,
103
+ /** How long a client may take to send its request; tests shorten it. */
104
+ requestTimeoutMs?: number,
105
+ /** How often a drain counts what still runs; tests shorten it. */
106
+ drainPollMs?: number): Promise<DaemonControlServer>;
107
+ export type DaemonControlReply = {
108
+ state: 'stopped';
109
+ holder: LockOwner | null;
110
+ } | {
111
+ state: 'running';
112
+ reply: Record<string, unknown>;
113
+ };
114
+ /**
115
+ * Ask the install's daemon. No token or no listening socket means nothing serves this install;
116
+ * a lock left behind is reported with its holder so a crashed process is visible.
117
+ */
118
+ export declare function requestDaemonControl(paths: DaemonControlPaths, op: DaemonControlOp, timeoutMs?: number): Promise<DaemonControlReply>;
119
+ /** One drain line: what still runs, the hold's bound, and whether nothing runs any more. */
120
+ export interface DrainProgress extends DrainCounts {
121
+ readonly bound: number;
122
+ readonly idle: boolean;
123
+ }
124
+ export type DrainOutcome =
125
+ /** Nothing runs; claims stay held until `release`. */
126
+ {
127
+ kind: 'idle';
128
+ }
129
+ /** The bound passed first; the daemon let go and changed nothing. */
130
+ | {
131
+ kind: 'bound';
132
+ bound: number;
133
+ running: number;
134
+ claimed: number;
135
+ } | {
136
+ kind: 'refused';
137
+ error: string;
138
+ }
139
+ /** The daemon stopped answering the drain; this side let go. */
140
+ | {
141
+ kind: 'silent';
142
+ error: string;
143
+ }
144
+ /** The connection ended before idle: the daemon stopped or died. */
145
+ | {
146
+ kind: 'closed';
147
+ };
148
+ export interface DaemonDrain {
149
+ readonly outcome: Promise<DrainOutcome>;
150
+ /** End the hold; the daemon claims again. */
151
+ release(): void;
152
+ }
153
+ /** How long a drain's client waits on the daemon; tests shorten them. */
154
+ export interface DrainDeadlines {
155
+ /** For the first line, which the daemon sends as soon as it holds. */
156
+ firstMs?: number;
157
+ /** Between lines: the daemon repeats its counts every 30 s, so two missed repeats. */
158
+ silenceMs?: number;
159
+ /** Past the daemon's own bound, which the daemon should have ended the drain at. */
160
+ graceMs?: number;
161
+ }
162
+ /**
163
+ * Hold the install's claims for as long as the returned drain is not released, and report each
164
+ * count the daemon sends. Null when nothing serves the install. The bound is the daemon's, but a
165
+ * wedged daemon would enforce nothing, so this side gives up too when the daemon goes quiet or
166
+ * outlives its own bound.
167
+ */
168
+ export declare function drainDaemon(paths: DaemonControlPaths, onProgress: (progress: DrainProgress) => void, deadlines?: DrainDeadlines): Promise<DaemonDrain | null>;
169
+ //# sourceMappingURL=daemon-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-control.d.ts","sourceRoot":"","sources":["../../../src/cli/runtime/daemon-control.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,441 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DRAIN_REPEAT_MS = exports.InstallBusyError = exports.RestorePendingError = void 0;
7
+ exports.daemonControlPaths = daemonControlPaths;
8
+ exports.restoreJournalPath = restoreJournalPath;
9
+ exports.refuseWhileRestoring = refuseWhileRestoring;
10
+ exports.acquireInstallLock = acquireInstallLock;
11
+ exports.lockHolder = lockHolder;
12
+ exports.startDaemonControl = startDaemonControl;
13
+ exports.requestDaemonControl = requestDaemonControl;
14
+ exports.drainDaemon = drainDaemon;
15
+ const node_crypto_1 = require("node:crypto");
16
+ const node_fs_1 = require("node:fs");
17
+ const node_net_1 = require("node:net");
18
+ const node_path_1 = require("node:path");
19
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
20
+ const prompt_js_1 = require("../prompt.js");
21
+ function daemonControlPaths(mamaRoot) {
22
+ const runtimeRoot = (0, node_path_1.join)(mamaRoot, 'runtime');
23
+ return {
24
+ lockPath: (0, node_path_1.join)(runtimeRoot, 'daemon.lock'),
25
+ holderPath: (0, node_path_1.join)(runtimeRoot, 'daemon.holder.json'),
26
+ socketPath: (0, node_path_1.join)(mamaRoot, 'daemon.sock'),
27
+ tokenPath: (0, node_path_1.join)(runtimeRoot, 'daemon.token'),
28
+ };
29
+ }
30
+ /** The journal an interrupted `mama restore` leaves; nothing may run on the install while it is there. */
31
+ function restoreJournalPath(mamaRoot) {
32
+ return (0, node_path_1.join)(mamaRoot, 'backups', '.restore-journal.json');
33
+ }
34
+ /** A half-switched install: a refusal, not a failure, so a service does not restart into it. */
35
+ class RestorePendingError extends prompt_js_1.CliInputError {
36
+ code = 'MAMA_RESTORE_PENDING';
37
+ constructor() {
38
+ super('An interrupted restore is unfinished; run mama restore --rollback first');
39
+ this.name = 'RestorePendingError';
40
+ }
41
+ }
42
+ exports.RestorePendingError = RestorePendingError;
43
+ /** Refuse to work on an install while a restore journal is open. */
44
+ function refuseWhileRestoring(mamaRoot) {
45
+ if ((0, node_fs_1.existsSync)(restoreJournalPath(mamaRoot)))
46
+ throw new RestorePendingError();
47
+ }
48
+ /** A CLI input error: the message names the holder and the fix, and carries no secret. */
49
+ class InstallBusyError extends prompt_js_1.CliInputError {
50
+ holder;
51
+ code = 'MAMA_INSTALL_BUSY';
52
+ constructor(holder, lockPath) {
53
+ super(holder === null
54
+ ? `MAMA is already running here (${lockPath}); stop it first: mama stop`
55
+ : `MAMA is already running here (${holder.command}, pid ${holder.pid}; ${lockPath}); stop it first: mama stop`);
56
+ this.holder = holder;
57
+ this.name = 'InstallBusyError';
58
+ }
59
+ }
60
+ exports.InstallBusyError = InstallBusyError;
61
+ function readHolder(path) {
62
+ try {
63
+ const value = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
64
+ return typeof value.pid === 'number' &&
65
+ typeof value.command === 'string' &&
66
+ typeof value.startedAt === 'number' &&
67
+ typeof value.nonce === 'string'
68
+ ? value
69
+ : null;
70
+ }
71
+ catch (error) {
72
+ if (error.code === 'ENOENT')
73
+ return null;
74
+ throw error;
75
+ }
76
+ }
77
+ function isBusy(error) {
78
+ return error.code === 'SQLITE_BUSY';
79
+ }
80
+ /**
81
+ * Take the install's lock: an exclusive transaction on the lock database, kept open for the
82
+ * process's life. A held lock refuses after `busyTimeoutMs`, which only outlasts the moment a
83
+ * `mama status` probe reads the file.
84
+ */
85
+ function acquireInstallLock(paths, command, options = {}) {
86
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(paths.lockPath, '..'), { recursive: true, mode: 0o700 });
87
+ const db = new better_sqlite3_1.default(paths.lockPath, { timeout: options.busyTimeoutMs ?? 2_000 });
88
+ try {
89
+ (0, node_fs_1.chmodSync)(paths.lockPath, 0o600);
90
+ db.pragma('locking_mode = EXCLUSIVE');
91
+ db.exec('BEGIN EXCLUSIVE');
92
+ }
93
+ catch (error) {
94
+ db.close();
95
+ if (isBusy(error))
96
+ throw new InstallBusyError(readHolder(paths.holderPath), paths.lockPath);
97
+ throw error;
98
+ }
99
+ // `pid` first: install/install.sh's Node move recovery reads it from the holder file with sed.
100
+ const owner = {
101
+ pid: process.pid,
102
+ command,
103
+ startedAt: Date.now(),
104
+ nonce: (0, node_crypto_1.randomUUID)(),
105
+ };
106
+ const staged = `${paths.holderPath}.${owner.nonce}`;
107
+ (0, node_fs_1.writeFileSync)(staged, `${JSON.stringify(owner)}\n`, { mode: 0o600, flag: 'wx' });
108
+ (0, node_fs_1.renameSync)(staged, paths.holderPath);
109
+ let released = false;
110
+ return {
111
+ owner,
112
+ release: () => {
113
+ if (released)
114
+ return;
115
+ released = true;
116
+ if (readHolder(paths.holderPath)?.nonce === owner.nonce)
117
+ (0, node_fs_1.rmSync)(paths.holderPath);
118
+ db.close();
119
+ },
120
+ };
121
+ }
122
+ /**
123
+ * The process that holds the install, or null when none does. Reading the lock database needs a
124
+ * shared lock, which the holder's exclusive one refuses; when nothing holds it, the read takes the
125
+ * shared lock for an instant only.
126
+ */
127
+ function lockHolder(paths) {
128
+ if (!(0, node_fs_1.existsSync)(paths.lockPath))
129
+ return null;
130
+ const db = new better_sqlite3_1.default(paths.lockPath, { readonly: true, timeout: 0 });
131
+ try {
132
+ db.pragma('schema_version');
133
+ return null;
134
+ }
135
+ catch (error) {
136
+ if (!isBusy(error))
137
+ throw error;
138
+ return (readHolder(paths.holderPath) ?? { pid: 0, command: 'unknown', startedAt: 0, nonce: 'unknown' });
139
+ }
140
+ finally {
141
+ db.close();
142
+ }
143
+ }
144
+ const MAX_REQUEST_BYTES = 4096;
145
+ /** A drain repeats its counts this often while they stay the same, so a waiting terminal sees why. */
146
+ exports.DRAIN_REPEAT_MS = 30_000;
147
+ /**
148
+ * Serve status, stop, a backend probe, a drain and an update's release to the CLI. Only the lock holder calls this, so
149
+ * removing a socket left by a dead holder never removes a live one. Each boot writes a new token; a
150
+ * request without it is refused. Every op but `drain` answers once and ends the connection. A
151
+ * drain keeps its connection open and holds claims for as long as it stays open: it sends its
152
+ * counts as lines until nothing runs, then says idle and goes on holding, so the stop that follows
153
+ * starts nothing new; a client that dies lets go. Past the hold's bound it sends the counts and
154
+ * ends, which lets go too.
155
+ */
156
+ async function startDaemonControl(paths, handlers,
157
+ /** How long a client may take to send its request; tests shorten it. */
158
+ requestTimeoutMs = 5_000,
159
+ /** How often a drain counts what still runs; tests shorten it. */
160
+ drainPollMs = 1_000) {
161
+ const token = (0, node_crypto_1.randomBytes)(32).toString('hex');
162
+ (0, node_fs_1.rmSync)(paths.tokenPath, { force: true });
163
+ (0, node_fs_1.writeFileSync)(paths.tokenPath, `${token}\n`, { mode: 0o600, flag: 'wx' });
164
+ (0, node_fs_1.rmSync)(paths.socketPath, { force: true });
165
+ const expected = Buffer.from(token, 'utf8');
166
+ // Open drains: the server's close waits for every connection, and a drain ends only when its
167
+ // client lets go, so closing the server ends them.
168
+ const drains = new Set();
169
+ const server = (0, node_net_1.createServer)((socket) => {
170
+ let buffer = '';
171
+ socket.setEncoding('utf8');
172
+ socket.setTimeout(requestTimeoutMs, () => socket.destroy());
173
+ socket.on('error', () => socket.destroy());
174
+ socket.on('data', (chunk) => {
175
+ buffer += chunk;
176
+ if (buffer.length > MAX_REQUEST_BYTES) {
177
+ socket.destroy();
178
+ return;
179
+ }
180
+ const newline = buffer.indexOf('\n');
181
+ if (newline === -1)
182
+ return;
183
+ const line = buffer.slice(0, newline);
184
+ buffer = '';
185
+ // The deadline is for sending a request; answering a probe takes a model turn.
186
+ socket.setTimeout(0);
187
+ void answer(line, socket).then((reply) => {
188
+ if (reply)
189
+ socket.end(`${JSON.stringify(reply)}\n`);
190
+ }, (error) => socket.end(`${JSON.stringify({ ok: false, error: error instanceof Error ? error.message : String(error) })}\n`));
191
+ });
192
+ });
193
+ function drain(socket) {
194
+ const hold = handlers.hold();
195
+ drains.add(socket);
196
+ const started = Date.now();
197
+ let last = '';
198
+ let lastAt = 0;
199
+ const timer = setInterval(tick, drainPollMs);
200
+ socket.once('close', () => {
201
+ clearInterval(timer);
202
+ drains.delete(socket);
203
+ hold.release();
204
+ });
205
+ function tick() {
206
+ // A throw here would escape the timer and end the daemon; the client gets it instead.
207
+ try {
208
+ const counts = hold.counts();
209
+ const idle = counts.running === 0 && counts.claimed === 0;
210
+ if (!idle && Date.now() - started >= hold.boundMs) {
211
+ clearInterval(timer);
212
+ socket.end(`${JSON.stringify({ ok: false, error: 'drain bound passed', bound: hold.boundMs, ...counts })}\n`);
213
+ return;
214
+ }
215
+ const line = JSON.stringify({ ok: true, drain: { ...counts, bound: hold.boundMs, idle } });
216
+ if (line !== last || Date.now() - lastAt >= exports.DRAIN_REPEAT_MS) {
217
+ socket.write(`${line}\n`);
218
+ last = line;
219
+ lastAt = Date.now();
220
+ }
221
+ // Nothing new is claimed while held, so idle stays idle; the hold goes on until the client
222
+ // closes or the daemon stops.
223
+ if (idle)
224
+ clearInterval(timer);
225
+ }
226
+ catch (error) {
227
+ clearInterval(timer);
228
+ socket.end(`${JSON.stringify({ ok: false, error: error instanceof Error ? error.message : String(error) })}\n`);
229
+ }
230
+ }
231
+ tick();
232
+ }
233
+ async function answer(line, socket) {
234
+ let request;
235
+ try {
236
+ request = JSON.parse(line);
237
+ }
238
+ catch {
239
+ return { ok: false, error: 'invalid request' };
240
+ }
241
+ const given = Buffer.from(typeof request.token === 'string' ? request.token : '', 'utf8');
242
+ if (given.length !== expected.length || !(0, node_crypto_1.timingSafeEqual)(given, expected)) {
243
+ return { ok: false, error: 'unauthorized' };
244
+ }
245
+ if (request.op === 'status')
246
+ return { ok: true, status: await handlers.status() };
247
+ if (request.op === 'stop') {
248
+ handlers.stop();
249
+ return { ok: true };
250
+ }
251
+ if (request.op === 'probe')
252
+ return { ok: true, probe: await handlers.probe() };
253
+ if (request.op === 'release')
254
+ return { ok: true, ...handlers.release() };
255
+ if (request.op === 'drain') {
256
+ drain(socket);
257
+ return null;
258
+ }
259
+ return { ok: false, error: 'unknown op' };
260
+ }
261
+ try {
262
+ await new Promise((resolve, reject) => {
263
+ server.once('error', reject);
264
+ server.listen(paths.socketPath, () => {
265
+ server.off('error', reject);
266
+ resolve();
267
+ });
268
+ });
269
+ }
270
+ catch (error) {
271
+ (0, node_fs_1.rmSync)(paths.tokenPath, { force: true });
272
+ throw error;
273
+ }
274
+ (0, node_fs_1.chmodSync)(paths.socketPath, 0o600);
275
+ return {
276
+ close: () => new Promise((resolve) => {
277
+ for (const socket of drains)
278
+ socket.destroy();
279
+ server.close(() => {
280
+ (0, node_fs_1.rmSync)(paths.socketPath, { force: true });
281
+ (0, node_fs_1.rmSync)(paths.tokenPath, { force: true });
282
+ resolve();
283
+ });
284
+ }),
285
+ };
286
+ }
287
+ /**
288
+ * Ask the install's daemon. No token or no listening socket means nothing serves this install;
289
+ * a lock left behind is reported with its holder so a crashed process is visible.
290
+ */
291
+ async function requestDaemonControl(paths, op, timeoutMs = 5_000) {
292
+ let token;
293
+ try {
294
+ token = (0, node_fs_1.readFileSync)(paths.tokenPath, 'utf8').trim();
295
+ }
296
+ catch (error) {
297
+ if (error.code !== 'ENOENT')
298
+ throw error;
299
+ return { state: 'stopped', holder: lockHolder(paths) };
300
+ }
301
+ return await new Promise((resolve, reject) => {
302
+ const socket = (0, node_net_1.connect)(paths.socketPath);
303
+ let data = '';
304
+ socket.setEncoding('utf8');
305
+ socket.setTimeout(timeoutMs, () => {
306
+ socket.destroy();
307
+ reject(new Error(`The daemon did not answer within ${timeoutMs} ms`));
308
+ });
309
+ socket.on('connect', () => socket.write(`${JSON.stringify({ token, op })}\n`));
310
+ socket.on('data', (chunk) => {
311
+ data += chunk;
312
+ });
313
+ socket.on('end', () => {
314
+ try {
315
+ resolve({ state: 'running', reply: JSON.parse(data) });
316
+ }
317
+ catch {
318
+ reject(new Error('The daemon sent an unreadable reply'));
319
+ }
320
+ });
321
+ socket.on('error', (error) => {
322
+ if (error.code !== 'ENOENT' && error.code !== 'ECONNREFUSED') {
323
+ reject(error);
324
+ return;
325
+ }
326
+ // Inside an event handler a throw would be uncaught; the caller gets it instead.
327
+ try {
328
+ resolve({ state: 'stopped', holder: lockHolder(paths) });
329
+ }
330
+ catch (holderError) {
331
+ reject(holderError);
332
+ }
333
+ });
334
+ });
335
+ }
336
+ /**
337
+ * Hold the install's claims for as long as the returned drain is not released, and report each
338
+ * count the daemon sends. Null when nothing serves the install. The bound is the daemon's, but a
339
+ * wedged daemon would enforce nothing, so this side gives up too when the daemon goes quiet or
340
+ * outlives its own bound.
341
+ */
342
+ async function drainDaemon(paths, onProgress, deadlines = {}) {
343
+ const firstMs = deadlines.firstMs ?? 5_000;
344
+ const silenceMs = deadlines.silenceMs ?? 2 * exports.DRAIN_REPEAT_MS + 5_000;
345
+ const graceMs = deadlines.graceMs ?? 30_000;
346
+ let token;
347
+ try {
348
+ token = (0, node_fs_1.readFileSync)(paths.tokenPath, 'utf8').trim();
349
+ }
350
+ catch (error) {
351
+ if (error.code !== 'ENOENT')
352
+ throw error;
353
+ return null;
354
+ }
355
+ return await new Promise((resolve, reject) => {
356
+ const socket = (0, node_net_1.connect)(paths.socketPath);
357
+ let connected = false;
358
+ let settled = false;
359
+ let silence;
360
+ let watchdog;
361
+ let resolveOutcome;
362
+ const outcome = new Promise((done) => {
363
+ resolveOutcome = done;
364
+ });
365
+ const settle = (result) => {
366
+ if (settled)
367
+ return;
368
+ settled = true;
369
+ clearTimeout(silence);
370
+ clearTimeout(watchdog);
371
+ resolveOutcome(result);
372
+ };
373
+ const quiet = (ms, error) => {
374
+ clearTimeout(silence);
375
+ silence = setTimeout(() => {
376
+ settle({ kind: 'silent', error });
377
+ socket.destroy();
378
+ }, ms);
379
+ };
380
+ let buffer = '';
381
+ socket.setEncoding('utf8');
382
+ socket.on('connect', () => {
383
+ connected = true;
384
+ socket.write(`${JSON.stringify({ token, op: 'drain' })}\n`);
385
+ quiet(firstMs, `the daemon did not answer the drain within ${firstMs} ms`);
386
+ resolve({ outcome, release: () => socket.destroy() });
387
+ });
388
+ socket.on('data', (chunk) => {
389
+ buffer += chunk;
390
+ for (let newline = buffer.indexOf('\n'); newline !== -1; newline = buffer.indexOf('\n')) {
391
+ const line = buffer.slice(0, newline);
392
+ buffer = buffer.slice(newline + 1);
393
+ let reply;
394
+ try {
395
+ reply = JSON.parse(line);
396
+ }
397
+ catch {
398
+ settle({ kind: 'refused', error: 'The daemon sent an unreadable reply' });
399
+ socket.destroy();
400
+ return;
401
+ }
402
+ if (reply.ok !== true) {
403
+ settle(reply.error === 'drain bound passed'
404
+ ? {
405
+ kind: 'bound',
406
+ bound: Number(reply.bound),
407
+ running: Number(reply.running),
408
+ claimed: Number(reply.claimed),
409
+ }
410
+ : { kind: 'refused', error: String(reply.error) });
411
+ continue;
412
+ }
413
+ const progress = reply.drain;
414
+ if (watchdog === undefined) {
415
+ watchdog = setTimeout(() => {
416
+ settle({
417
+ kind: 'silent',
418
+ error: `the daemon did not end the drain at its bound of ${progress.bound} ms`,
419
+ });
420
+ socket.destroy();
421
+ }, progress.bound + graceMs);
422
+ }
423
+ quiet(silenceMs, `the daemon sent nothing on the drain for ${silenceMs} ms`);
424
+ onProgress(progress);
425
+ if (progress.idle)
426
+ settle({ kind: 'idle' });
427
+ }
428
+ });
429
+ // A settled outcome stays; a close before any answer is the daemon going away.
430
+ socket.on('close', () => settle({ kind: 'closed' }));
431
+ socket.on('error', (error) => {
432
+ if (connected)
433
+ return; // the close that follows settles the outcome
434
+ if (error.code === 'ENOENT' || error.code === 'ECONNREFUSED')
435
+ resolve(null);
436
+ else
437
+ reject(error);
438
+ });
439
+ });
440
+ }
441
+ //# sourceMappingURL=daemon-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-control.js","sourceRoot":"","sources":["../../../src/cli/runtime/daemon-control.ts"],"names":[],"mappings":"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"}