crewly 1.20.174 → 1.20.176

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 (71) hide show
  1. package/config/skills/orchestrator/restart-crewly/SKILL.md +11 -23
  2. package/config/skills/orchestrator/restart-crewly/execute.sh +7 -5
  3. package/dist/backend/backend/src/constants.d.ts +62 -0
  4. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  5. package/dist/backend/backend/src/constants.js +62 -0
  6. package/dist/backend/backend/src/constants.js.map +1 -1
  7. package/dist/backend/backend/src/controllers/system/system-control.controller.d.ts +67 -0
  8. package/dist/backend/backend/src/controllers/system/system-control.controller.d.ts.map +1 -0
  9. package/dist/backend/backend/src/controllers/system/system-control.controller.js +183 -0
  10. package/dist/backend/backend/src/controllers/system/system-control.controller.js.map +1 -0
  11. package/dist/backend/backend/src/controllers/system/system.controller.d.ts +0 -13
  12. package/dist/backend/backend/src/controllers/system/system.controller.d.ts.map +1 -1
  13. package/dist/backend/backend/src/controllers/system/system.controller.js +0 -87
  14. package/dist/backend/backend/src/controllers/system/system.controller.js.map +1 -1
  15. package/dist/backend/backend/src/index.d.ts +7 -0
  16. package/dist/backend/backend/src/index.d.ts.map +1 -1
  17. package/dist/backend/backend/src/index.js +84 -1
  18. package/dist/backend/backend/src/index.js.map +1 -1
  19. package/dist/backend/backend/src/routes/modules/system.routes.d.ts.map +1 -1
  20. package/dist/backend/backend/src/routes/modules/system.routes.js +4 -2
  21. package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -1
  22. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  23. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +15 -1
  24. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  25. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
  26. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +7 -0
  27. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  28. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +27 -0
  29. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +92 -1
  31. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/system/auto-update.service.d.ts +58 -0
  33. package/dist/backend/backend/src/services/system/auto-update.service.d.ts.map +1 -1
  34. package/dist/backend/backend/src/services/system/auto-update.service.js +128 -52
  35. package/dist/backend/backend/src/services/system/auto-update.service.js.map +1 -1
  36. package/dist/backend/backend/src/services/system/auto-update.utils.d.ts +7 -0
  37. package/dist/backend/backend/src/services/system/auto-update.utils.d.ts.map +1 -1
  38. package/dist/backend/backend/src/services/system/auto-update.utils.js +14 -0
  39. package/dist/backend/backend/src/services/system/auto-update.utils.js.map +1 -1
  40. package/dist/backend/backend/src/services/system/restart-replacement.d.ts +78 -0
  41. package/dist/backend/backend/src/services/system/restart-replacement.d.ts.map +1 -0
  42. package/dist/backend/backend/src/services/system/restart-replacement.js +109 -0
  43. package/dist/backend/backend/src/services/system/restart-replacement.js.map +1 -0
  44. package/dist/backend/backend/src/services/system/supervisor-detect.d.ts +78 -0
  45. package/dist/backend/backend/src/services/system/supervisor-detect.d.ts.map +1 -0
  46. package/dist/backend/backend/src/services/system/supervisor-detect.js +171 -0
  47. package/dist/backend/backend/src/services/system/supervisor-detect.js.map +1 -0
  48. package/dist/backend/backend/src/services/system/system-control.service.d.ts +337 -0
  49. package/dist/backend/backend/src/services/system/system-control.service.d.ts.map +1 -0
  50. package/dist/backend/backend/src/services/system/system-control.service.js +574 -0
  51. package/dist/backend/backend/src/services/system/system-control.service.js.map +1 -0
  52. package/dist/backend/build-info.json +2 -2
  53. package/dist/cli/backend/src/constants.d.ts +62 -0
  54. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  55. package/dist/cli/backend/src/constants.js +62 -0
  56. package/dist/cli/backend/src/constants.js.map +1 -1
  57. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  58. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +15 -1
  59. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  60. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +27 -0
  61. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  62. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +92 -1
  63. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  64. package/dist/cli/backend/src/services/system/auto-update.utils.d.ts +7 -0
  65. package/dist/cli/backend/src/services/system/auto-update.utils.d.ts.map +1 -1
  66. package/dist/cli/backend/src/services/system/auto-update.utils.js +14 -0
  67. package/dist/cli/backend/src/services/system/auto-update.utils.js.map +1 -1
  68. package/frontend/dist/assets/{index-36e85ac8.js → index-0726afab.js} +281 -281
  69. package/frontend/dist/assets/{index-15501404.css → index-0c5449b5.css} +1 -1
  70. package/frontend/dist/index.html +2 -2
  71. package/package.json +1 -1
@@ -0,0 +1,574 @@
1
+ /**
2
+ * System Control Service — the owner's Upgrade and Restart buttons.
3
+ *
4
+ * Jenkins-style "safe restart" for Crewly
5
+ * (specs/2026-10-01-upgrade-restart-controls.md):
6
+ *
7
+ * - **Status.** Running version, latest on npm, install kind, who relaunches
8
+ * the backend, agents mid-turn, and the current / last action.
9
+ * - **Upgrade** (`when: idle | now`). npm global installs only. It reuses the
10
+ * AutoUpdateService install path (same prefix, same npm, same verify), then
11
+ * restarts. A source checkout is refused: it is updated with git.
12
+ * - **Restart** (`when: idle | now`). The graceful drained shutdown, exiting
13
+ * with RESTART_REQUESTED. When nothing is known to relaunch the backend, a
14
+ * detached launcher is started first so the machine never stays down.
15
+ * - **When idle** waits until no agent is mid-turn, capped (30 min), then
16
+ * goes ahead. Asking again with `now` cuts the wait short.
17
+ * - **One at a time.** A second request while one is running is refused,
18
+ * as is any request while a shutdown is already under way.
19
+ * - **Survives the restart.** Progress and outcome are kept in
20
+ * `<crewlyHome>/system-action.json`; the next boot settles the record
21
+ * ("Restarted at …", "Upgraded to x.y.z", or what went wrong), so the
22
+ * dashboard can show it after it reconnects.
23
+ *
24
+ * All I/O goes through {@link SystemControlDeps}.
25
+ *
26
+ * @module services/system/system-control.service
27
+ */
28
+ import * as fs from 'fs';
29
+ import * as path from 'path';
30
+ import { randomUUID } from 'crypto';
31
+ import { PROCESS_EXIT_CODES, SYSTEM_CONTROL_CONSTANTS } from '../../constants.js';
32
+ import { isNewerVersion } from './auto-update.utils.js';
33
+ /** Statuses that mean "still running". */
34
+ const ACTIVE_STATUSES = new Set(['waiting-idle', 'installing', 'restarting']);
35
+ /**
36
+ * Map the AutoUpdate install kind onto the public one.
37
+ *
38
+ * @param install - Install info
39
+ * @returns Public kind
40
+ */
41
+ export function toPublicInstallKind(install) {
42
+ if (install.kind === 'npm-global')
43
+ return 'npm-global';
44
+ if (install.kind === 'dev-checkout')
45
+ return 'dev-checkout';
46
+ return 'other';
47
+ }
48
+ /**
49
+ * Read the persisted action record.
50
+ *
51
+ * @param file - State file
52
+ * @returns The record, or null when missing / malformed
53
+ */
54
+ export function readActionRecord(file) {
55
+ try {
56
+ const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
57
+ return parsed && typeof parsed.id === 'string' && typeof parsed.status === 'string' ? parsed : null;
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ /**
64
+ * Write the action record atomically.
65
+ *
66
+ * @param file - State file
67
+ * @param record - Record
68
+ */
69
+ export function writeActionRecord(file, record) {
70
+ fs.mkdirSync(path.dirname(file), { recursive: true });
71
+ const tmp = `${file}.${process.pid}.tmp`;
72
+ fs.writeFileSync(tmp, JSON.stringify(record, null, 2), 'utf-8');
73
+ fs.renameSync(tmp, file);
74
+ }
75
+ /**
76
+ * Upgrade / restart controller for the running backend.
77
+ */
78
+ export class SystemControlService {
79
+ deps;
80
+ static instance = null;
81
+ action = null;
82
+ stateFile;
83
+ /** Resolves the current idle wait early ("now" pressed while waiting) */
84
+ cutIdleWaitShort = null;
85
+ /**
86
+ * @param deps - Injected I/O
87
+ */
88
+ constructor(deps) {
89
+ this.deps = deps;
90
+ this.stateFile = path.join(deps.crewlyHome, SYSTEM_CONTROL_CONSTANTS.STATE_FILE);
91
+ }
92
+ /**
93
+ * Register the process-wide instance.
94
+ *
95
+ * @param service - Instance, or null to clear
96
+ */
97
+ static setInstance(service) {
98
+ SystemControlService.instance = service;
99
+ }
100
+ /**
101
+ * The process-wide instance, when the server registered one.
102
+ *
103
+ * @returns The instance or null
104
+ */
105
+ static getInstance() {
106
+ return SystemControlService.instance;
107
+ }
108
+ /**
109
+ * Boot: settle the record a previous process left behind, so the
110
+ * dashboard can say "Restarted at …" / "Upgraded to x.y.z" after it
111
+ * reconnects.
112
+ */
113
+ handleBoot() {
114
+ const record = readActionRecord(this.stateFile);
115
+ if (!record || !ACTIVE_STATUSES.has(record.status) || record.pid === this.deps.pid)
116
+ return;
117
+ const now = new Date(this.deps.now()).toISOString();
118
+ const running = this.deps.currentVersion;
119
+ let settled;
120
+ if (record.status === 'restarting') {
121
+ if (record.kind === 'upgrade' && record.toVersion && running !== record.toVersion) {
122
+ settled = {
123
+ ...record,
124
+ status: 'failed',
125
+ message: `Crewly came back on ${running ?? 'an unknown version'} instead of ${record.toVersion}.`,
126
+ };
127
+ }
128
+ else {
129
+ settled = {
130
+ ...record,
131
+ status: 'completed',
132
+ message: record.kind === 'upgrade' ? `Upgraded to ${running} and restarted at ${now}.` : `Restarted at ${now}.`,
133
+ };
134
+ }
135
+ }
136
+ else {
137
+ settled = {
138
+ ...record,
139
+ status: 'interrupted',
140
+ message: record.kind === 'upgrade'
141
+ ? 'Crewly stopped before the upgrade finished. Nothing was installed or the install was not confirmed; try again.'
142
+ : 'Crewly stopped before the restart started.',
143
+ };
144
+ }
145
+ settled = { ...settled, completedAt: now, updatedAt: now, resultVersion: running };
146
+ this.action = settled;
147
+ this.persist();
148
+ this.deps.logger.info('Previous upgrade/restart settled at boot', {
149
+ id: settled.id,
150
+ kind: settled.kind,
151
+ status: settled.status,
152
+ requestedBy: settled.requestedBy,
153
+ message: settled.message,
154
+ });
155
+ }
156
+ /**
157
+ * Whether an upgrade or restart from this process is still running.
158
+ *
159
+ * @returns True while one is
160
+ */
161
+ isActionInProgress() {
162
+ return !!this.action && ACTIVE_STATUSES.has(this.action.status) && this.action.pid === this.deps.pid;
163
+ }
164
+ /**
165
+ * The current or last action (this boot, or the one settled at boot).
166
+ *
167
+ * @returns The record or null
168
+ */
169
+ getAction() {
170
+ if (this.action)
171
+ return this.action;
172
+ return readActionRecord(this.stateFile);
173
+ }
174
+ /**
175
+ * How the backend comes back after an exit.
176
+ *
177
+ * @param supervisor - Supervisor info
178
+ * @returns supervisor or replacement
179
+ */
180
+ relaunchMethod(supervisor) {
181
+ return supervisor.willRelaunch === 'yes' ? 'supervisor' : 'replacement';
182
+ }
183
+ /**
184
+ * Status for the dashboard.
185
+ *
186
+ * @param options - `refresh` re-asks the registry when the cached answer is over a minute old
187
+ * @returns Status
188
+ */
189
+ async getStatus(options = {}) {
190
+ const { install, currentVersion } = this.deps;
191
+ let latest = null;
192
+ try {
193
+ latest = await this.deps.fetchLatestVersion(options.refresh ? SYSTEM_CONTROL_CONSTANTS.REGISTRY_MAX_AGE_MS : SYSTEM_CONTROL_CONSTANTS.STATUS_REGISTRY_MAX_AGE_MS);
194
+ }
195
+ catch {
196
+ latest = null;
197
+ }
198
+ const updateAvailable = !!latest && !!currentVersion && isNewerVersion(latest, currentVersion);
199
+ const installKind = toPublicInstallKind(install);
200
+ const busy = this.inProgressReason();
201
+ const supervisor = this.deps.getSupervisor();
202
+ let upgradeBlockedReason = null;
203
+ if (installKind === 'dev-checkout')
204
+ upgradeBlockedReason = SYSTEM_CONTROL_CONSTANTS.MESSAGES.DEV_CHECKOUT;
205
+ else if (installKind === 'other')
206
+ upgradeBlockedReason = SYSTEM_CONTROL_CONSTANTS.MESSAGES.NOT_NPM_GLOBAL;
207
+ else if (busy)
208
+ upgradeBlockedReason = busy;
209
+ else if (!latest)
210
+ upgradeBlockedReason = SYSTEM_CONTROL_CONSTANTS.MESSAGES.REGISTRY_UNREACHABLE;
211
+ else if (!updateAvailable)
212
+ upgradeBlockedReason = `Crewly is up to date (${currentVersion}).`;
213
+ else if (!this.deps.getInstaller())
214
+ upgradeBlockedReason = SYSTEM_CONTROL_CONSTANTS.MESSAGES.UNAVAILABLE;
215
+ return {
216
+ currentVersion,
217
+ latestVersion: latest,
218
+ updateAvailable,
219
+ installKind,
220
+ packageRoot: install.packageRoot,
221
+ canUpgrade: upgradeBlockedReason === null,
222
+ upgradeBlockedReason,
223
+ canRestart: busy === null,
224
+ restartBlockedReason: busy,
225
+ supervisor,
226
+ relaunch: this.relaunchMethod(supervisor),
227
+ busyAgents: this.safeBusyAgents(),
228
+ inProgress: busy !== null,
229
+ action: this.getAction(),
230
+ bootId: this.deps.bootId,
231
+ startedAt: this.deps.startedAt,
232
+ };
233
+ }
234
+ /**
235
+ * Why nothing new can start right now (null when it can).
236
+ *
237
+ * @returns Owner-readable reason or null
238
+ */
239
+ inProgressReason() {
240
+ if (this.isActionInProgress() && this.action) {
241
+ return this.action.kind === 'upgrade'
242
+ ? `An upgrade to ${this.action.toVersion} is already in progress.`
243
+ : 'A restart is already in progress.';
244
+ }
245
+ if (this.deps.isShutdownInProgress())
246
+ return SYSTEM_CONTROL_CONSTANTS.MESSAGES.RESTART_IN_PROGRESS;
247
+ if (this.deps.getInstaller()?.isBusy())
248
+ return 'An automatic update is running right now. Try again in a few minutes.';
249
+ return null;
250
+ }
251
+ /**
252
+ * Busy agents, never throwing.
253
+ *
254
+ * @returns Agents mid-turn
255
+ */
256
+ safeBusyAgents() {
257
+ try {
258
+ return this.deps.getBusyAgents();
259
+ }
260
+ catch {
261
+ return [];
262
+ }
263
+ }
264
+ /**
265
+ * Escalate a running "when idle" wait of the same kind to "now".
266
+ *
267
+ * @param kind - Requested kind
268
+ * @param request - Request
269
+ * @returns Accepted answer, or null when this is not an escalation
270
+ */
271
+ tryEscalate(kind, request) {
272
+ const action = this.action;
273
+ if (request.when !== 'now' ||
274
+ !action ||
275
+ !this.isActionInProgress() ||
276
+ action.kind !== kind ||
277
+ action.status !== 'waiting-idle' ||
278
+ !this.cutIdleWaitShort) {
279
+ return null;
280
+ }
281
+ this.deps.logger.info(`${kind === 'upgrade' ? 'Upgrade' : 'Restart'}: "now" requested while waiting for idle`, {
282
+ id: action.id,
283
+ requestedBy: request.actor,
284
+ });
285
+ this.update({ when: 'now', message: `${request.actor} asked to go ahead now.` });
286
+ this.cutIdleWaitShort();
287
+ return { ok: true, action: this.action, escalated: true };
288
+ }
289
+ /**
290
+ * Refusal for "something is already running", or null.
291
+ *
292
+ * @returns Refusal or null
293
+ */
294
+ busyRefusal() {
295
+ if (this.isActionInProgress()) {
296
+ return { ok: false, httpStatus: 409, code: SYSTEM_CONTROL_CONSTANTS.CODES.IN_PROGRESS, error: this.inProgressReason() };
297
+ }
298
+ const reason = this.inProgressReason();
299
+ if (reason) {
300
+ return { ok: false, httpStatus: 409, code: SYSTEM_CONTROL_CONSTANTS.CODES.RESTART_IN_PROGRESS, error: reason };
301
+ }
302
+ return null;
303
+ }
304
+ /**
305
+ * Owner pressed "Upgrade".
306
+ *
307
+ * @param request - When, and who
308
+ * @returns Accepted (work continues in the background) or a refusal
309
+ */
310
+ async requestUpgrade(request) {
311
+ const { install, currentVersion } = this.deps;
312
+ if (install.kind === 'dev-checkout') {
313
+ this.deps.logger.info('Upgrade refused: source checkout', { requestedBy: request.actor, packageRoot: install.packageRoot });
314
+ return { ok: false, httpStatus: 409, code: SYSTEM_CONTROL_CONSTANTS.CODES.DEV_CHECKOUT, error: SYSTEM_CONTROL_CONSTANTS.MESSAGES.DEV_CHECKOUT };
315
+ }
316
+ if (install.kind !== 'npm-global') {
317
+ this.deps.logger.info('Upgrade refused: not an npm global install', { requestedBy: request.actor, detail: install.detail });
318
+ return { ok: false, httpStatus: 409, code: SYSTEM_CONTROL_CONSTANTS.CODES.NOT_NPM_GLOBAL, error: SYSTEM_CONTROL_CONSTANTS.MESSAGES.NOT_NPM_GLOBAL };
319
+ }
320
+ const escalated = this.tryEscalate('upgrade', request);
321
+ if (escalated)
322
+ return escalated;
323
+ const busy = this.busyRefusal();
324
+ if (busy)
325
+ return busy;
326
+ const installer = this.deps.getInstaller();
327
+ if (!installer) {
328
+ return { ok: false, httpStatus: 503, code: SYSTEM_CONTROL_CONSTANTS.CODES.UNAVAILABLE, error: SYSTEM_CONTROL_CONSTANTS.MESSAGES.UNAVAILABLE };
329
+ }
330
+ let latest = null;
331
+ try {
332
+ latest = await this.deps.fetchLatestVersion(SYSTEM_CONTROL_CONSTANTS.REGISTRY_MAX_AGE_MS);
333
+ }
334
+ catch {
335
+ latest = null;
336
+ }
337
+ if (!latest) {
338
+ return { ok: false, httpStatus: 502, code: SYSTEM_CONTROL_CONSTANTS.CODES.REGISTRY_UNREACHABLE, error: SYSTEM_CONTROL_CONSTANTS.MESSAGES.REGISTRY_UNREACHABLE };
339
+ }
340
+ if (!currentVersion || !isNewerVersion(latest, currentVersion)) {
341
+ return { ok: false, httpStatus: 409, code: SYSTEM_CONTROL_CONSTANTS.CODES.UP_TO_DATE, error: `Crewly is already up to date (${currentVersion ?? latest}).` };
342
+ }
343
+ // The registry await gave another request a chance to start.
344
+ const raced = this.busyRefusal();
345
+ if (raced)
346
+ return raced;
347
+ const action = this.begin('upgrade', request, latest);
348
+ installer.appendLogLine(`${new Date(this.deps.now()).toISOString()} Manual upgrade to ${latest} requested by ${request.actor} (${request.when})`);
349
+ void this.runUpgrade(installer, latest).catch((error) => this.fail(`Upgrade crashed: ${errorText(error)}`));
350
+ return { ok: true, action };
351
+ }
352
+ /**
353
+ * Owner pressed "Restart".
354
+ *
355
+ * @param request - When, and who
356
+ * @returns Accepted (work continues in the background) or a refusal
357
+ */
358
+ async requestRestart(request) {
359
+ const escalated = this.tryEscalate('restart', request);
360
+ if (escalated)
361
+ return escalated;
362
+ const busy = this.busyRefusal();
363
+ if (busy)
364
+ return busy;
365
+ const action = this.begin('restart', request, null);
366
+ void this.runRestart().catch((error) => this.fail(`Restart crashed: ${errorText(error)}`));
367
+ return { ok: true, action };
368
+ }
369
+ /**
370
+ * Create and persist a new action.
371
+ *
372
+ * @param kind - upgrade or restart
373
+ * @param request - Request
374
+ * @param toVersion - Upgrade target
375
+ * @returns The record
376
+ */
377
+ begin(kind, request, toVersion) {
378
+ const now = new Date(this.deps.now()).toISOString();
379
+ const supervisor = this.deps.getSupervisor();
380
+ const label = kind === 'upgrade' ? `Upgrade to ${toVersion}` : 'Restart';
381
+ this.action = {
382
+ id: randomUUID(),
383
+ kind,
384
+ when: request.when,
385
+ status: request.when === 'idle' ? 'waiting-idle' : kind === 'upgrade' ? 'installing' : 'restarting',
386
+ requestedBy: request.actor,
387
+ requestedAt: now,
388
+ updatedAt: now,
389
+ fromVersion: this.deps.currentVersion,
390
+ toVersion,
391
+ pid: this.deps.pid,
392
+ relaunch: this.relaunchMethod(supervisor),
393
+ message: request.when === 'idle' ? `${label} will start when no agent is mid-turn.` : `${label} is starting.`,
394
+ };
395
+ this.persist();
396
+ this.deps.logger.info(`${label} requested`, {
397
+ id: this.action.id,
398
+ when: request.when,
399
+ requestedBy: request.actor,
400
+ fromVersion: this.deps.currentVersion,
401
+ supervisor: supervisor.kind,
402
+ willRelaunch: supervisor.willRelaunch,
403
+ });
404
+ return this.action;
405
+ }
406
+ /**
407
+ * Upgrade body: (wait for idle) → install → verify → marker → restart.
408
+ *
409
+ * @param installer - AutoUpdate install path
410
+ * @param version - Target
411
+ */
412
+ async runUpgrade(installer, version) {
413
+ if (this.action?.when === 'idle')
414
+ await this.waitForIdle();
415
+ if (this.deps.isShutdownInProgress()) {
416
+ this.fail('Crewly started shutting down for another reason before the upgrade began.');
417
+ return;
418
+ }
419
+ this.update({ status: 'installing', message: `Installing ${version}…` });
420
+ const attempt = await installer.installVersion(version);
421
+ if (!attempt.ok) {
422
+ this.deps.logger.warn('Manual upgrade install failed; not restarting', { version, outcome: attempt.outcome, reason: attempt.reason, ...attempt.details });
423
+ this.fail(`Could not install ${version}: ${attempt.reason}. Crewly keeps running ${this.deps.currentVersion}.`);
424
+ return;
425
+ }
426
+ installer.writeUpgradeMarker(this.deps.currentVersion ?? 'unknown', version);
427
+ const restarted = this.restartNow(`owner upgrade ${this.deps.currentVersion} -> ${version}`, `Installed ${version}. Restarting…`);
428
+ if (!restarted)
429
+ installer.clearUpgradeMarker();
430
+ }
431
+ /**
432
+ * Restart body: (wait for idle) → restart.
433
+ */
434
+ async runRestart() {
435
+ if (this.action?.when === 'idle')
436
+ await this.waitForIdle();
437
+ if (this.deps.isShutdownInProgress()) {
438
+ this.fail('Crewly started shutting down for another reason before the restart began.');
439
+ return;
440
+ }
441
+ await this.deps.sleep(SYSTEM_CONTROL_CONSTANTS.RESPONSE_FLUSH_MS);
442
+ this.restartNow('owner restart', 'Restarting… agents finish their current turn first.');
443
+ }
444
+ /**
445
+ * Make sure something brings the backend back, then run the graceful
446
+ * restart.
447
+ *
448
+ * @param reason - Shutdown reason (logs)
449
+ * @param message - Owner-readable progress
450
+ * @returns False when the restart could not be started
451
+ */
452
+ restartNow(reason, message) {
453
+ const supervisor = this.deps.getSupervisor();
454
+ const relaunch = this.relaunchMethod(supervisor);
455
+ if (relaunch === 'replacement') {
456
+ try {
457
+ this.deps.spawnReplacement(supervisor.willRelaunch === 'unknown');
458
+ this.deps.logger.info('Started the replacement launcher; it brings Crewly back after this process exits', {
459
+ supervisor: supervisor.kind,
460
+ });
461
+ }
462
+ catch (error) {
463
+ this.fail(`Could not arrange for Crewly to come back (${errorText(error)}), so it was not restarted.`);
464
+ return false;
465
+ }
466
+ }
467
+ this.update({ status: 'restarting', relaunch, message });
468
+ this.deps.logger.info('Restarting Crewly', { reason, relaunch, requestedBy: this.action?.requestedBy });
469
+ let started = false;
470
+ try {
471
+ started = this.deps.requestGracefulRestart(reason);
472
+ }
473
+ catch (error) {
474
+ this.deps.logger.warn('Graceful restart unavailable; exiting directly', { error: errorText(error) });
475
+ }
476
+ if (!started) {
477
+ this.deps.logger.warn('No graceful shutdown handler; exiting with the restart code');
478
+ this.deps.exit(PROCESS_EXIT_CODES.RESTART_REQUESTED);
479
+ }
480
+ return true;
481
+ }
482
+ /**
483
+ * Wait until no agent is mid-turn, at most IDLE_WAIT_CAP_MS; a later "now"
484
+ * request ends the wait at once.
485
+ */
486
+ async waitForIdle() {
487
+ const deadline = this.deps.now() + SYSTEM_CONTROL_CONSTANTS.IDLE_WAIT_CAP_MS;
488
+ let cut = false;
489
+ const cutPromise = new Promise((resolve) => {
490
+ this.cutIdleWaitShort = () => {
491
+ cut = true;
492
+ resolve();
493
+ };
494
+ });
495
+ let lastBusy = '';
496
+ try {
497
+ for (;;) {
498
+ if (cut) {
499
+ this.update({ idleWaitEndedBy: 'now' });
500
+ return;
501
+ }
502
+ const busy = this.safeBusyAgents().map((a) => a.session);
503
+ if (busy.length === 0) {
504
+ this.update({ idleWaitEndedBy: 'idle', waitingFor: [] });
505
+ this.deps.logger.info('No agent is mid-turn; going ahead', { id: this.action?.id });
506
+ return;
507
+ }
508
+ if (this.deps.now() >= deadline) {
509
+ this.update({ idleWaitEndedBy: 'cap', waitingFor: busy });
510
+ this.deps.logger.info('Waited the maximum for agents to go idle; going ahead (the restart drain still lets turns finish)', {
511
+ id: this.action?.id,
512
+ busy,
513
+ });
514
+ return;
515
+ }
516
+ const key = busy.join(',');
517
+ if (key !== lastBusy) {
518
+ lastBusy = key;
519
+ this.update({ waitingFor: busy, message: `Waiting for ${busy.length} agent${busy.length === 1 ? '' : 's'} to finish: ${busy.join(', ')}.` });
520
+ }
521
+ await Promise.race([this.deps.sleep(SYSTEM_CONTROL_CONSTANTS.IDLE_POLL_MS), cutPromise]);
522
+ }
523
+ }
524
+ finally {
525
+ this.cutIdleWaitShort = null;
526
+ }
527
+ }
528
+ /**
529
+ * Mark the current action failed.
530
+ *
531
+ * @param message - Owner-readable reason
532
+ */
533
+ fail(message) {
534
+ if (!this.action)
535
+ return;
536
+ const now = new Date(this.deps.now()).toISOString();
537
+ this.update({ status: 'failed', message, completedAt: now, resultVersion: this.deps.currentVersion });
538
+ this.deps.logger.warn('Upgrade/restart failed', { id: this.action.id, kind: this.action.kind, message, requestedBy: this.action.requestedBy });
539
+ }
540
+ /**
541
+ * Merge a patch into the current action and persist it.
542
+ *
543
+ * @param patch - Fields to change
544
+ */
545
+ update(patch) {
546
+ if (!this.action)
547
+ return;
548
+ this.action = { ...this.action, ...patch, updatedAt: new Date(this.deps.now()).toISOString() };
549
+ this.persist();
550
+ }
551
+ /**
552
+ * Write the current action (best-effort).
553
+ */
554
+ persist() {
555
+ if (!this.action)
556
+ return;
557
+ try {
558
+ writeActionRecord(this.stateFile, this.action);
559
+ }
560
+ catch (error) {
561
+ this.deps.logger.warn('Could not save upgrade/restart progress', { error: errorText(error) });
562
+ }
563
+ }
564
+ }
565
+ /**
566
+ * Error text.
567
+ *
568
+ * @param error - Anything thrown
569
+ * @returns Message
570
+ */
571
+ function errorText(error) {
572
+ return error instanceof Error ? error.message : String(error);
573
+ }
574
+ //# sourceMappingURL=system-control.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-control.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/system/system-control.service.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  {
2
- "commit": "16684dd54ffa9bdc9bf61e94f2e485d76a41df8b",
3
- "builtAt": "2026-10-01T04:06:11.280Z"
2
+ "commit": "c62f8ff859f1073619387857d5f8b073b5f89504",
3
+ "builtAt": "2026-10-01T12:46:42.110Z"
4
4
  }