crewly 1.20.237 → 1.20.239
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.
- package/config/constants.ts +19 -0
- package/dist/backend/backend/src/constants.d.ts +13 -3
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +6 -3
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js +3 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/system-control.controller.d.ts +31 -1
- package/dist/backend/backend/src/controllers/system/system-control.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/system-control.controller.js +83 -3
- package/dist/backend/backend/src/controllers/system/system-control.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +27 -3
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +10 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts +8 -6
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +18 -17
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +4 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js +5 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
- package/dist/backend/backend/src/services/restart/restart-drain.service.d.ts +35 -0
- package/dist/backend/backend/src/services/restart/restart-drain.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/restart/restart-drain.service.js +57 -0
- package/dist/backend/backend/src/services/restart/restart-drain.service.js.map +1 -1
- package/dist/backend/backend/src/services/system/shutdown-marker.d.ts +41 -0
- package/dist/backend/backend/src/services/system/shutdown-marker.d.ts.map +1 -0
- package/dist/backend/backend/src/services/system/shutdown-marker.js +59 -0
- package/dist/backend/backend/src/services/system/shutdown-marker.js.map +1 -0
- package/dist/backend/backend/src/services/system/system-control.service.d.ts +53 -3
- package/dist/backend/backend/src/services/system/system-control.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/system/system-control.service.js +130 -9
- package/dist/backend/backend/src/services/system/system-control.service.js.map +1 -1
- package/dist/backend/backend/src/services/system/wind-down.service.d.ts +145 -0
- package/dist/backend/backend/src/services/system/wind-down.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/system/wind-down.service.js +231 -0
- package/dist/backend/backend/src/services/system/wind-down.service.js.map +1 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js +6 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/trigger-engine.service.js +4 -0
- package/dist/backend/backend/src/services/v3/trigger-engine.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.js +4 -0
- package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/backend/config/constants.d.ts +19 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +19 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +13 -3
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +6 -3
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +10 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts +8 -6
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js +18 -17
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/cli/backend/src/services/restart/restart-drain.service.d.ts +35 -0
- package/dist/cli/backend/src/services/restart/restart-drain.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/restart/restart-drain.service.js +57 -0
- package/dist/cli/backend/src/services/restart/restart-drain.service.js.map +1 -1
- package/dist/cli/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/workflow/cron-task.service.js +4 -0
- package/dist/cli/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/cli/cli/src/commands/service.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/service.js +13 -1
- package/dist/cli/cli/src/commands/service.js.map +1 -1
- package/dist/cli/cli/src/commands/start.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/start.js +11 -0
- package/dist/cli/cli/src/commands/start.js.map +1 -1
- package/dist/cli/cli/src/utils/shutdown-marker.d.ts +44 -0
- package/dist/cli/cli/src/utils/shutdown-marker.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/shutdown-marker.js +70 -0
- package/dist/cli/cli/src/utils/shutdown-marker.js.map +1 -0
- package/dist/cli/config/constants.d.ts +19 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +19 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/frontend/dist/assets/{index-a719c15a.js → index-c9630c55.js} +276 -276
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -76,6 +76,8 @@ export interface GracefulShutdownRequest {
|
|
|
76
76
|
reason: string;
|
|
77
77
|
/** Process exit code at the end of shutdown */
|
|
78
78
|
exitCode?: number;
|
|
79
|
+
/** False skips the in-flight-turn drain (a wind-down already waited for the agents) */
|
|
80
|
+
drain?: boolean;
|
|
79
81
|
}
|
|
80
82
|
/**
|
|
81
83
|
* Resolve the drain timeout from the environment.
|
|
@@ -113,6 +115,10 @@ export declare class RestartDrainService {
|
|
|
113
115
|
private paused;
|
|
114
116
|
private pauseReason;
|
|
115
117
|
private draining;
|
|
118
|
+
private windingDown;
|
|
119
|
+
private windDownOwnsPause;
|
|
120
|
+
/** Runs inside {@link runAsWindDownNotice}: the wind-down note may pass the delivery pause */
|
|
121
|
+
private readonly noticeScope;
|
|
116
122
|
private skipRequested;
|
|
117
123
|
private wakeSleeper;
|
|
118
124
|
private queueCounter;
|
|
@@ -134,6 +140,35 @@ export declare class RestartDrainService {
|
|
|
134
140
|
* @returns True while paused
|
|
135
141
|
*/
|
|
136
142
|
isDeliveryPaused(): boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Whether a wind-down (agents asked to pause before a shutdown / restart)
|
|
145
|
+
* is running. New work is held while it is: autopilot ticks, reconciler
|
|
146
|
+
* passes, cron fires and new agent starts check this.
|
|
147
|
+
*
|
|
148
|
+
* @returns True during the wind-down
|
|
149
|
+
*/
|
|
150
|
+
isWindingDown(): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Start holding new work for a wind-down: deliveries stay on the
|
|
153
|
+
* persistent queues (owner messages included — they are kept, not lost)
|
|
154
|
+
* and the {@link isWindingDown} gates close. Idempotent.
|
|
155
|
+
*
|
|
156
|
+
* @param reason - Why (for logs)
|
|
157
|
+
*/
|
|
158
|
+
beginWindDown(reason: string): void;
|
|
159
|
+
/**
|
|
160
|
+
* End the wind-down hold without shutting down (the action failed). Only
|
|
161
|
+
* lifts a pause the wind-down itself set; a real shutdown keeps its own.
|
|
162
|
+
*/
|
|
163
|
+
abortWindDown(): void;
|
|
164
|
+
/**
|
|
165
|
+
* Run a delivery of the wind-down note: it passes the delivery pause that
|
|
166
|
+
* holds everything else.
|
|
167
|
+
*
|
|
168
|
+
* @param fn - The delivery
|
|
169
|
+
* @returns What `fn` returns
|
|
170
|
+
*/
|
|
171
|
+
runAsWindDownNotice<T>(fn: () => T): T;
|
|
137
172
|
/**
|
|
138
173
|
* Whether the drain wait is running right now.
|
|
139
174
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restart-drain.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/restart/restart-drain.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"restart-drain.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/restart/restart-drain.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @module services/restart/restart-drain
|
|
18
18
|
*/
|
|
19
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
19
20
|
import { LoggerService } from '../core/logger.service.js';
|
|
20
21
|
import { SAFE_RESTART } from '../../constants.js';
|
|
21
22
|
import { InFlightTurnTracker } from './in-flight-turn-tracker.service.js';
|
|
@@ -75,6 +76,10 @@ export class RestartDrainService {
|
|
|
75
76
|
paused = false;
|
|
76
77
|
pauseReason = null;
|
|
77
78
|
draining = false;
|
|
79
|
+
windingDown = false;
|
|
80
|
+
windDownOwnsPause = false;
|
|
81
|
+
/** Runs inside {@link runAsWindDownNotice}: the wind-down note may pass the delivery pause */
|
|
82
|
+
noticeScope = new AsyncLocalStorage();
|
|
78
83
|
skipRequested = false;
|
|
79
84
|
wakeSleeper = null;
|
|
80
85
|
queueCounter = null;
|
|
@@ -106,8 +111,60 @@ export class RestartDrainService {
|
|
|
106
111
|
* @returns True while paused
|
|
107
112
|
*/
|
|
108
113
|
isDeliveryPaused() {
|
|
114
|
+
// The wind-down note itself is the one write allowed while paused.
|
|
115
|
+
if (this.paused && this.noticeScope.getStore() === true)
|
|
116
|
+
return false;
|
|
109
117
|
return this.paused;
|
|
110
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Whether a wind-down (agents asked to pause before a shutdown / restart)
|
|
121
|
+
* is running. New work is held while it is: autopilot ticks, reconciler
|
|
122
|
+
* passes, cron fires and new agent starts check this.
|
|
123
|
+
*
|
|
124
|
+
* @returns True during the wind-down
|
|
125
|
+
*/
|
|
126
|
+
isWindingDown() {
|
|
127
|
+
return this.windingDown;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Start holding new work for a wind-down: deliveries stay on the
|
|
131
|
+
* persistent queues (owner messages included — they are kept, not lost)
|
|
132
|
+
* and the {@link isWindingDown} gates close. Idempotent.
|
|
133
|
+
*
|
|
134
|
+
* @param reason - Why (for logs)
|
|
135
|
+
*/
|
|
136
|
+
beginWindDown(reason) {
|
|
137
|
+
if (this.windingDown)
|
|
138
|
+
return;
|
|
139
|
+
this.windingDown = true;
|
|
140
|
+
this.windDownOwnsPause = !this.paused;
|
|
141
|
+
this.pauseDelivery(reason);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* End the wind-down hold without shutting down (the action failed). Only
|
|
145
|
+
* lifts a pause the wind-down itself set; a real shutdown keeps its own.
|
|
146
|
+
*/
|
|
147
|
+
abortWindDown() {
|
|
148
|
+
if (!this.windingDown)
|
|
149
|
+
return;
|
|
150
|
+
this.windingDown = false;
|
|
151
|
+
if (this.windDownOwnsPause && this.paused) {
|
|
152
|
+
this.paused = false;
|
|
153
|
+
this.pauseReason = null;
|
|
154
|
+
this.logger.info('Wind-down aborted; agent message delivery resumed');
|
|
155
|
+
}
|
|
156
|
+
this.windDownOwnsPause = false;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Run a delivery of the wind-down note: it passes the delivery pause that
|
|
160
|
+
* holds everything else.
|
|
161
|
+
*
|
|
162
|
+
* @param fn - The delivery
|
|
163
|
+
* @returns What `fn` returns
|
|
164
|
+
*/
|
|
165
|
+
runAsWindDownNotice(fn) {
|
|
166
|
+
return this.noticeScope.run(true, fn);
|
|
167
|
+
}
|
|
111
168
|
/**
|
|
112
169
|
* Whether the drain wait is running right now.
|
|
113
170
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restart-drain.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/restart/restart-drain.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,aAAa,EAAmB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAqB,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"restart-drain.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/restart/restart-drain.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shutdown marker: `<crewlyHome>/run/shutdown-requested`.
|
|
3
|
+
*
|
|
4
|
+
* Written when the owner shuts Crewly down (as opposed to restarting it). A
|
|
5
|
+
* supervisor that relaunches Crewly whenever it exits — the macOS
|
|
6
|
+
* `crewly-start.command` loop — checks the file first and stays down.
|
|
7
|
+
* `crewly start`, a fresh supervisor launch and the backend's own boot clear
|
|
8
|
+
* it, so the next manual launch always works.
|
|
9
|
+
*
|
|
10
|
+
* @module services/system/shutdown-marker
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Path of the marker.
|
|
14
|
+
*
|
|
15
|
+
* @param crewlyHome - Crewly home directory
|
|
16
|
+
* @returns Absolute path
|
|
17
|
+
*/
|
|
18
|
+
export declare function shutdownMarkerPath(crewlyHome: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Write the marker (who and when, for whoever finds it).
|
|
21
|
+
*
|
|
22
|
+
* @param crewlyHome - Crewly home directory
|
|
23
|
+
* @param pid - Backend pid that requested the shutdown
|
|
24
|
+
* @param now - Clock
|
|
25
|
+
* @throws When the file cannot be written
|
|
26
|
+
*/
|
|
27
|
+
export declare function writeShutdownMarker(crewlyHome: string, pid?: number, now?: () => number): void;
|
|
28
|
+
/**
|
|
29
|
+
* Remove the marker; absent is fine.
|
|
30
|
+
*
|
|
31
|
+
* @param crewlyHome - Crewly home directory
|
|
32
|
+
*/
|
|
33
|
+
export declare function clearShutdownMarker(crewlyHome: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the marker exists.
|
|
36
|
+
*
|
|
37
|
+
* @param crewlyHome - Crewly home directory
|
|
38
|
+
* @returns True when a shutdown was requested and no start has cleared it
|
|
39
|
+
*/
|
|
40
|
+
export declare function hasShutdownMarker(crewlyHome: string): boolean;
|
|
41
|
+
//# sourceMappingURL=shutdown-marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown-marker.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/system/shutdown-marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,MAAoB,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,IAAI,CAIrH;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAM5D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE7D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shutdown marker: `<crewlyHome>/run/shutdown-requested`.
|
|
3
|
+
*
|
|
4
|
+
* Written when the owner shuts Crewly down (as opposed to restarting it). A
|
|
5
|
+
* supervisor that relaunches Crewly whenever it exits — the macOS
|
|
6
|
+
* `crewly-start.command` loop — checks the file first and stays down.
|
|
7
|
+
* `crewly start`, a fresh supervisor launch and the backend's own boot clear
|
|
8
|
+
* it, so the next manual launch always works.
|
|
9
|
+
*
|
|
10
|
+
* @module services/system/shutdown-marker
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { SAFE_RESTART } from '../../constants.js';
|
|
15
|
+
/**
|
|
16
|
+
* Path of the marker.
|
|
17
|
+
*
|
|
18
|
+
* @param crewlyHome - Crewly home directory
|
|
19
|
+
* @returns Absolute path
|
|
20
|
+
*/
|
|
21
|
+
export function shutdownMarkerPath(crewlyHome) {
|
|
22
|
+
return path.join(crewlyHome, SAFE_RESTART.SHUTDOWN_MARKER_DIR, SAFE_RESTART.SHUTDOWN_MARKER_FILE);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Write the marker (who and when, for whoever finds it).
|
|
26
|
+
*
|
|
27
|
+
* @param crewlyHome - Crewly home directory
|
|
28
|
+
* @param pid - Backend pid that requested the shutdown
|
|
29
|
+
* @param now - Clock
|
|
30
|
+
* @throws When the file cannot be written
|
|
31
|
+
*/
|
|
32
|
+
export function writeShutdownMarker(crewlyHome, pid = process.pid, now = Date.now) {
|
|
33
|
+
const file = shutdownMarkerPath(crewlyHome);
|
|
34
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
35
|
+
fs.writeFileSync(file, `${JSON.stringify({ requestedAt: new Date(now()).toISOString(), pid })}\n`, 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Remove the marker; absent is fine.
|
|
39
|
+
*
|
|
40
|
+
* @param crewlyHome - Crewly home directory
|
|
41
|
+
*/
|
|
42
|
+
export function clearShutdownMarker(crewlyHome) {
|
|
43
|
+
try {
|
|
44
|
+
fs.rmSync(shutdownMarkerPath(crewlyHome), { force: true });
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// best-effort
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Whether the marker exists.
|
|
52
|
+
*
|
|
53
|
+
* @param crewlyHome - Crewly home directory
|
|
54
|
+
* @returns True when a shutdown was requested and no start has cleared it
|
|
55
|
+
*/
|
|
56
|
+
export function hasShutdownMarker(crewlyHome) {
|
|
57
|
+
return fs.existsSync(shutdownMarkerPath(crewlyHome));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=shutdown-marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown-marker.js","sourceRoot":"","sources":["../../../../../../backend/src/services/system/shutdown-marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACpD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,mBAAmB,EAAE,YAAY,CAAC,oBAAoB,CAAC,CAAC;AACnG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE,MAAoB,IAAI,CAAC,GAAG;IAC9G,MAAM,IAAI,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC5C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7G,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACrD,IAAI,CAAC;QACJ,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACR,cAAc;IACf,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IACnD,OAAO,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -28,14 +28,15 @@
|
|
|
28
28
|
import { SYSTEM_CONTROL_CONSTANTS } from '../../constants.js';
|
|
29
29
|
import type { InstallAttempt } from './auto-update.service.js';
|
|
30
30
|
import type { InstallInfo } from './auto-update.utils.js';
|
|
31
|
+
import type { WindDownEnd, WindDownProgress, WindDownRequest } from './wind-down.service.js';
|
|
31
32
|
import type { SupervisorInfo } from './supervisor-detect.js';
|
|
32
33
|
import { type InputGuardReport } from './input-guard-release-check.js';
|
|
33
34
|
/** `when` choice of the buttons. */
|
|
34
35
|
export type SystemActionWhen = (typeof SYSTEM_CONTROL_CONSTANTS.WHEN_VALUES)[number];
|
|
35
36
|
/** Which button was pressed. */
|
|
36
|
-
export type SystemActionKind = 'upgrade' | 'restart';
|
|
37
|
+
export type SystemActionKind = 'upgrade' | 'restart' | 'shutdown';
|
|
37
38
|
/** Where an action is. */
|
|
38
|
-
export type SystemActionStatus = 'waiting-idle' | 'installing' | 'restarting' | 'completed' | 'failed' | 'interrupted';
|
|
39
|
+
export type SystemActionStatus = 'waiting-idle' | 'winding-down' | 'stopping' | 'installing' | 'restarting' | 'completed' | 'failed' | 'interrupted';
|
|
39
40
|
/** Install kind as the dashboard sees it. */
|
|
40
41
|
export type PublicInstallKind = 'npm-global' | 'dev-checkout' | 'other';
|
|
41
42
|
/** How the backend comes back after it exits. */
|
|
@@ -96,6 +97,8 @@ export interface UpdateStatus {
|
|
|
96
97
|
busyAgents: BusyAgentInfo[];
|
|
97
98
|
/** Some upgrade / restart / shutdown is under way */
|
|
98
99
|
inProgress: boolean;
|
|
100
|
+
/** Agents being asked to wind down before a restart / shutdown (null when none is) */
|
|
101
|
+
windDown: WindDownProgress | null;
|
|
99
102
|
/** Current or last action */
|
|
100
103
|
action: SystemActionRecord | null;
|
|
101
104
|
/** Changes on every boot; the dashboard uses it to see the backend came back */
|
|
@@ -151,7 +154,21 @@ export interface SystemControlDeps {
|
|
|
151
154
|
/** The AutoUpdateService install path (null when it did not start) */
|
|
152
155
|
getInstaller: () => UpgradeInstaller | null;
|
|
153
156
|
/** Run the graceful drained shutdown with RESTART_REQUESTED; false when no handler */
|
|
154
|
-
requestGracefulRestart: (reason: string
|
|
157
|
+
requestGracefulRestart: (reason: string, options?: {
|
|
158
|
+
exitCode?: number;
|
|
159
|
+
drain?: boolean;
|
|
160
|
+
}) => boolean;
|
|
161
|
+
/** Tell the agents to wind down and wait (restart now / shutdown); absent: the step is skipped */
|
|
162
|
+
windDown?: {
|
|
163
|
+
run: (request: WindDownRequest) => Promise<WindDownEnd>;
|
|
164
|
+
skip: () => boolean;
|
|
165
|
+
abort: () => void;
|
|
166
|
+
getProgress: () => WindDownProgress | null;
|
|
167
|
+
};
|
|
168
|
+
/** Write `<crewlyHome>/run/shutdown-requested` so a supervisor stays down */
|
|
169
|
+
writeShutdownMarker?: () => void;
|
|
170
|
+
/** Remove the shutdown marker */
|
|
171
|
+
clearShutdownMarker?: () => void;
|
|
155
172
|
/** Last resort when no graceful handler exists */
|
|
156
173
|
exit: (code: number) => void;
|
|
157
174
|
/** Start the detached launcher that brings the backend back */
|
|
@@ -174,6 +191,8 @@ export interface SystemActionRequest {
|
|
|
174
191
|
actor: string;
|
|
175
192
|
/** Owner override: restart onto the new build even when the input-guard check fails */
|
|
176
193
|
force?: boolean;
|
|
194
|
+
/** Wind-down grace period (seconds) for a restart now / shutdown */
|
|
195
|
+
graceSeconds?: number;
|
|
177
196
|
}
|
|
178
197
|
/**
|
|
179
198
|
* Map the AutoUpdate install kind onto the public one.
|
|
@@ -297,6 +316,37 @@ export declare class SystemControlService {
|
|
|
297
316
|
* @returns Accepted (work continues in the background) or a refusal
|
|
298
317
|
*/
|
|
299
318
|
requestRestart(request: SystemActionRequest): Promise<SystemActionAccepted | SystemActionRefusal>;
|
|
319
|
+
/**
|
|
320
|
+
* Owner pressed "Shut down": tell the agents to wind down, wait for them
|
|
321
|
+
* (or the grace period), stop the agents and the backend, and leave a
|
|
322
|
+
* marker so no supervisor brings Crewly back.
|
|
323
|
+
*
|
|
324
|
+
* @param request - Who, and the grace period (`when` is ignored)
|
|
325
|
+
* @returns Accepted (work continues in the background) or a refusal
|
|
326
|
+
*/
|
|
327
|
+
requestShutdown(request: Pick<SystemActionRequest, 'actor' | 'graceSeconds'>): Promise<SystemActionAccepted | SystemActionRefusal>;
|
|
328
|
+
/**
|
|
329
|
+
* Skip the wait of a running wind-down ("Skip waiting"): the agents are
|
|
330
|
+
* stopped now, the turns they had open are saved and resumed next start.
|
|
331
|
+
*
|
|
332
|
+
* @param actor - Who (logs)
|
|
333
|
+
* @returns True when a wind-down was running
|
|
334
|
+
*/
|
|
335
|
+
skipWindDown(actor: string): boolean;
|
|
336
|
+
/**
|
|
337
|
+
* Wind the agents down; false when it could not run (it never throws).
|
|
338
|
+
*
|
|
339
|
+
* @param kind - Restart or shutdown
|
|
340
|
+
* @param graceSeconds - Requested grace period
|
|
341
|
+
*/
|
|
342
|
+
private windDownAgents;
|
|
343
|
+
/**
|
|
344
|
+
* Shutdown body: wind down → marker → graceful exit (no drain: the
|
|
345
|
+
* wind-down was the wait).
|
|
346
|
+
*
|
|
347
|
+
* @param graceSeconds - Requested grace period
|
|
348
|
+
*/
|
|
349
|
+
private runShutdown;
|
|
300
350
|
/**
|
|
301
351
|
* Create and persist a new action.
|
|
302
352
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-control.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/system/system-control.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,EAAsB,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EASN,KAAK,gBAAgB,EACrB,MAAM,gCAAgC,CAAC;AAExC,oCAAoC;AACpC,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,wBAAwB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErF,gCAAgC;AAChC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"system-control.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/system/system-control.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,7 +32,7 @@ import { PROCESS_EXIT_CODES, SYSTEM_CONTROL_CONSTANTS } from '../../constants.js
|
|
|
32
32
|
import { isNewerVersion } from './auto-update.utils.js';
|
|
33
33
|
import { clearBlockedBuild, composeBlockNotice, describeBlock, onDiskWarning, readBlockedBuild, recordBlockNotified, wasBlockNotified, writeBlockedBuild, } from './input-guard-release-check.js';
|
|
34
34
|
/** Statuses that mean "still running". */
|
|
35
|
-
const ACTIVE_STATUSES = new Set(['waiting-idle', 'installing', 'restarting']);
|
|
35
|
+
const ACTIVE_STATUSES = new Set(['waiting-idle', 'winding-down', 'installing', 'restarting', 'stopping']);
|
|
36
36
|
/**
|
|
37
37
|
* Map the AutoUpdate install kind onto the public one.
|
|
38
38
|
*
|
|
@@ -120,7 +120,10 @@ export class SystemControlService {
|
|
|
120
120
|
const now = new Date(this.deps.now()).toISOString();
|
|
121
121
|
const running = this.deps.currentVersion;
|
|
122
122
|
let settled;
|
|
123
|
-
if (record.status === '
|
|
123
|
+
if (record.status === 'stopping') {
|
|
124
|
+
settled = { ...record, status: 'completed', message: `Crewly was shut down and was started again at ${now}.` };
|
|
125
|
+
}
|
|
126
|
+
else if (record.status === 'restarting') {
|
|
124
127
|
if (record.kind === 'upgrade' && record.toVersion && running !== record.toVersion) {
|
|
125
128
|
settled = {
|
|
126
129
|
...record,
|
|
@@ -142,7 +145,9 @@ export class SystemControlService {
|
|
|
142
145
|
status: 'interrupted',
|
|
143
146
|
message: record.kind === 'upgrade'
|
|
144
147
|
? 'Crewly stopped before the upgrade finished. Nothing was installed or the install was not confirmed; try again.'
|
|
145
|
-
:
|
|
148
|
+
: record.kind === 'shutdown'
|
|
149
|
+
? 'Crewly stopped before the shutdown finished.'
|
|
150
|
+
: 'Crewly stopped before the restart started.',
|
|
146
151
|
};
|
|
147
152
|
}
|
|
148
153
|
settled = { ...settled, completedAt: now, updatedAt: now, resultVersion: running };
|
|
@@ -229,6 +234,7 @@ export class SystemControlService {
|
|
|
229
234
|
relaunch: this.relaunchMethod(supervisor),
|
|
230
235
|
busyAgents: this.safeBusyAgents(),
|
|
231
236
|
inProgress: busy !== null,
|
|
237
|
+
windDown: this.deps.windDown?.getProgress() ?? null,
|
|
232
238
|
action: this.getAction(),
|
|
233
239
|
bootId: this.deps.bootId,
|
|
234
240
|
startedAt: this.deps.startedAt,
|
|
@@ -369,9 +375,98 @@ export class SystemControlService {
|
|
|
369
375
|
if (busy)
|
|
370
376
|
return busy;
|
|
371
377
|
const action = this.begin('restart', request, null);
|
|
372
|
-
void this.runRestart().catch((error) => this.fail(`Restart crashed: ${errorText(error)}`));
|
|
378
|
+
void this.runRestart(request.graceSeconds).catch((error) => this.fail(`Restart crashed: ${errorText(error)}`));
|
|
373
379
|
return { ok: true, action };
|
|
374
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* Owner pressed "Shut down": tell the agents to wind down, wait for them
|
|
383
|
+
* (or the grace period), stop the agents and the backend, and leave a
|
|
384
|
+
* marker so no supervisor brings Crewly back.
|
|
385
|
+
*
|
|
386
|
+
* @param request - Who, and the grace period (`when` is ignored)
|
|
387
|
+
* @returns Accepted (work continues in the background) or a refusal
|
|
388
|
+
*/
|
|
389
|
+
async requestShutdown(request) {
|
|
390
|
+
const busy = this.busyRefusal();
|
|
391
|
+
if (busy)
|
|
392
|
+
return busy;
|
|
393
|
+
if (!this.deps.windDown || !this.deps.writeShutdownMarker) {
|
|
394
|
+
return { ok: false, httpStatus: 503, code: SYSTEM_CONTROL_CONSTANTS.CODES.UNAVAILABLE, error: SYSTEM_CONTROL_CONSTANTS.MESSAGES.UNAVAILABLE };
|
|
395
|
+
}
|
|
396
|
+
const action = this.begin('shutdown', { when: 'now', actor: request.actor }, null);
|
|
397
|
+
void this.runShutdown(request.graceSeconds).catch((error) => this.fail(`Shutdown crashed: ${errorText(error)}`));
|
|
398
|
+
return { ok: true, action };
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Skip the wait of a running wind-down ("Skip waiting"): the agents are
|
|
402
|
+
* stopped now, the turns they had open are saved and resumed next start.
|
|
403
|
+
*
|
|
404
|
+
* @param actor - Who (logs)
|
|
405
|
+
* @returns True when a wind-down was running
|
|
406
|
+
*/
|
|
407
|
+
skipWindDown(actor) {
|
|
408
|
+
const skipped = this.deps.windDown?.skip() === true;
|
|
409
|
+
if (skipped) {
|
|
410
|
+
this.deps.logger.info('Wind-down: owner chose to skip waiting', { requestedBy: actor });
|
|
411
|
+
this.update({ message: `${actor} chose to skip waiting for the agents.` });
|
|
412
|
+
}
|
|
413
|
+
return skipped;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Wind the agents down; false when it could not run (it never throws).
|
|
417
|
+
*
|
|
418
|
+
* @param kind - Restart or shutdown
|
|
419
|
+
* @param graceSeconds - Requested grace period
|
|
420
|
+
*/
|
|
421
|
+
async windDownAgents(kind, graceSeconds) {
|
|
422
|
+
const windDown = this.deps.windDown;
|
|
423
|
+
if (!windDown)
|
|
424
|
+
return null;
|
|
425
|
+
this.update({
|
|
426
|
+
status: 'winding-down',
|
|
427
|
+
message: kind === 'shutdown' ? 'Asking the agents to stop at a safe point before shutting down…' : 'Asking the agents to stop at a safe point before restarting…',
|
|
428
|
+
});
|
|
429
|
+
try {
|
|
430
|
+
return await windDown.run({ kind, ...(graceSeconds !== undefined ? { graceSeconds } : {}) });
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
this.deps.logger.warn('Wind-down failed; carrying on', { error: errorText(error) });
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Shutdown body: wind down → marker → graceful exit (no drain: the
|
|
439
|
+
* wind-down was the wait).
|
|
440
|
+
*
|
|
441
|
+
* @param graceSeconds - Requested grace period
|
|
442
|
+
*/
|
|
443
|
+
async runShutdown(graceSeconds) {
|
|
444
|
+
await this.deps.sleep(SYSTEM_CONTROL_CONSTANTS.RESPONSE_FLUSH_MS);
|
|
445
|
+
const ended = await this.windDownAgents('shutdown', graceSeconds);
|
|
446
|
+
try {
|
|
447
|
+
this.deps.writeShutdownMarker?.();
|
|
448
|
+
}
|
|
449
|
+
catch (error) {
|
|
450
|
+
this.fail(`Could not write the shutdown marker (${errorText(error)}); Crewly would come back by itself, so it was not shut down.`);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
this.update({
|
|
454
|
+
status: 'stopping',
|
|
455
|
+
relaunch: null,
|
|
456
|
+
idleWaitEndedBy: ended === 'skipped' ? 'now' : ended === 'grace' ? 'cap' : 'idle',
|
|
457
|
+
message: 'Stopping the agents and Crewly…',
|
|
458
|
+
});
|
|
459
|
+
this.deps.logger.info('Shutting Crewly down', { requestedBy: this.action?.requestedBy, windDownEnded: ended });
|
|
460
|
+
let started = false;
|
|
461
|
+
try {
|
|
462
|
+
started = this.deps.requestGracefulRestart('owner shutdown', { exitCode: PROCESS_EXIT_CODES.SUCCESS, drain: false });
|
|
463
|
+
}
|
|
464
|
+
catch (error) {
|
|
465
|
+
this.deps.logger.warn('Graceful shutdown unavailable; exiting directly', { error: errorText(error) });
|
|
466
|
+
}
|
|
467
|
+
if (!started)
|
|
468
|
+
this.deps.exit(PROCESS_EXIT_CODES.SUCCESS);
|
|
469
|
+
}
|
|
375
470
|
/**
|
|
376
471
|
* Create and persist a new action.
|
|
377
472
|
*
|
|
@@ -383,12 +478,18 @@ export class SystemControlService {
|
|
|
383
478
|
begin(kind, request, toVersion) {
|
|
384
479
|
const now = new Date(this.deps.now()).toISOString();
|
|
385
480
|
const supervisor = this.deps.getSupervisor();
|
|
386
|
-
const label = kind === 'upgrade' ? `Upgrade to ${toVersion}` : 'Restart';
|
|
481
|
+
const label = kind === 'upgrade' ? `Upgrade to ${toVersion}` : kind === 'shutdown' ? 'Shutdown' : 'Restart';
|
|
387
482
|
this.action = {
|
|
388
483
|
id: randomUUID(),
|
|
389
484
|
kind,
|
|
390
485
|
when: request.when,
|
|
391
|
-
status: request.when === 'idle'
|
|
486
|
+
status: request.when === 'idle'
|
|
487
|
+
? 'waiting-idle'
|
|
488
|
+
: kind === 'upgrade'
|
|
489
|
+
? 'installing'
|
|
490
|
+
: kind === 'shutdown' || this.deps.windDown
|
|
491
|
+
? 'winding-down'
|
|
492
|
+
: 'restarting',
|
|
392
493
|
requestedBy: request.actor,
|
|
393
494
|
requestedAt: now,
|
|
394
495
|
updatedAt: now,
|
|
@@ -529,9 +630,21 @@ export class SystemControlService {
|
|
|
529
630
|
/**
|
|
530
631
|
* Restart body: (wait for idle) → restart.
|
|
531
632
|
*/
|
|
532
|
-
async runRestart() {
|
|
633
|
+
async runRestart(graceSeconds) {
|
|
533
634
|
if (this.action?.when === 'idle')
|
|
534
635
|
await this.waitForIdle();
|
|
636
|
+
// Nothing was mid-turn after a "when idle" wait: nobody to tell. Every
|
|
637
|
+
// other path (restart now, a "now" that cut the wait, the wait's cap)
|
|
638
|
+
// asks the agents to wind down first.
|
|
639
|
+
const windDownNeeded = this.action?.idleWaitEndedBy !== 'idle';
|
|
640
|
+
if (windDownNeeded) {
|
|
641
|
+
await this.deps.sleep(SYSTEM_CONTROL_CONSTANTS.RESPONSE_FLUSH_MS);
|
|
642
|
+
const ended = await this.windDownAgents('restart', graceSeconds);
|
|
643
|
+
if (ended !== null) {
|
|
644
|
+
this.restartNow('owner restart', 'Restarting…', { drain: false });
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
535
648
|
if (this.deps.isShutdownInProgress()) {
|
|
536
649
|
this.fail('Crewly started shutting down for another reason before the restart began.');
|
|
537
650
|
return;
|
|
@@ -547,7 +660,7 @@ export class SystemControlService {
|
|
|
547
660
|
* @param message - Owner-readable progress
|
|
548
661
|
* @returns False when the restart could not be started
|
|
549
662
|
*/
|
|
550
|
-
restartNow(reason, message) {
|
|
663
|
+
restartNow(reason, message, options = {}) {
|
|
551
664
|
const supervisor = this.deps.getSupervisor();
|
|
552
665
|
const relaunch = this.relaunchMethod(supervisor);
|
|
553
666
|
if (relaunch === 'replacement') {
|
|
@@ -566,7 +679,7 @@ export class SystemControlService {
|
|
|
566
679
|
this.deps.logger.info('Restarting Crewly', { reason, relaunch, requestedBy: this.action?.requestedBy });
|
|
567
680
|
let started = false;
|
|
568
681
|
try {
|
|
569
|
-
started = this.deps.requestGracefulRestart(reason);
|
|
682
|
+
started = options.drain === false ? this.deps.requestGracefulRestart(reason, { drain: false }) : this.deps.requestGracefulRestart(reason);
|
|
570
683
|
}
|
|
571
684
|
catch (error) {
|
|
572
685
|
this.deps.logger.warn('Graceful restart unavailable; exiting directly', { error: errorText(error) });
|
|
@@ -630,6 +743,14 @@ export class SystemControlService {
|
|
|
630
743
|
*/
|
|
631
744
|
fail(message) {
|
|
632
745
|
this.forceGuard = false;
|
|
746
|
+
// The process keeps running: lift the wind-down hold and the marker.
|
|
747
|
+
try {
|
|
748
|
+
this.deps.windDown?.abort();
|
|
749
|
+
this.deps.clearShutdownMarker?.();
|
|
750
|
+
}
|
|
751
|
+
catch {
|
|
752
|
+
// best-effort
|
|
753
|
+
}
|
|
633
754
|
if (!this.action)
|
|
634
755
|
return;
|
|
635
756
|
const now = new Date(this.deps.now()).toISOString();
|